Mercurial > emacs
changeset 46076:819af351608b
(x_focus_changed): New function.
(x_detect_focus_change): New function.
(XTread_socket): Call x_detect_focus_change for FocusIn/FocusOut
EnterNotify and LeaveNotify to track X focus changes.
author | Jan Djärv <jan.h.d@swipnet.se> |
---|---|
date | Fri, 28 Jun 2002 19:42:48 +0000 |
parents | 39e3c9d9b655 |
children | afcc2cec9ba0 |
files | src/xterm.c |
diffstat | 1 files changed, 157 insertions(+), 49 deletions(-) [+] |
line wrap: on
line diff
--- a/src/xterm.c Fri Jun 28 19:41:21 2002 +0000 +++ b/src/xterm.c Fri Jun 28 19:42:48 2002 +0000 @@ -466,6 +466,16 @@ static void frame_highlight P_ ((struct frame *)); static void frame_unhighlight P_ ((struct frame *)); static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *)); +static int x_focus_changed P_ ((int, + int, + struct x_display_info *, + struct frame *, + struct input_event *, + int)); +static int x_detect_focus_change P_ ((struct x_display_info *, + XEvent *, + struct input_event *, + int)); static void XTframe_rehighlight P_ ((struct frame *)); static void x_frame_rehighlight P_ ((struct x_display_info *)); static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *)); @@ -6291,6 +6301,121 @@ x_frame_rehighlight (dpyinfo); } +/* Handle FocusIn and FocusOut state changes for FRAME. + If FRAME has focus and there exists more than one frame, puts + an FOCUS_IN_EVENT into BUFP. + Returns number of events inserted into BUFP. */ + +static int +x_focus_changed (type, state, dpyinfo, frame, bufp, numchars) + int type; + int state; + struct x_display_info *dpyinfo; + struct frame *frame; + struct input_event *bufp; + int numchars; +{ + int nr_events = 0; + + if (type == FocusIn) + { + if (dpyinfo->x_focus_event_frame != frame) + { + x_new_focus_frame (dpyinfo, frame); + dpyinfo->x_focus_event_frame = frame; + + /* Don't stop displaying the initial startup message + for a switch-frame event we don't need. */ + if (numchars > 0 + && GC_NILP (Vterminal_frame) + && GC_CONSP (Vframe_list) + && !GC_NILP (XCDR (Vframe_list))) + { + bufp->kind = FOCUS_IN_EVENT; + XSETFRAME (bufp->frame_or_window, frame); + bufp->arg = Qnil; + ++bufp; + numchars--; + ++nr_events; + } + } + + frame->output_data.x->focus_state |= state; + +#ifdef HAVE_X_I18N + if (FRAME_XIC (frame)) + XSetICFocus (FRAME_XIC (frame)); +#endif + } + else if (type == FocusOut) + { + frame->output_data.x->focus_state &= ~state; + + if (dpyinfo->x_focus_event_frame == frame) + { + dpyinfo->x_focus_event_frame = 0; + x_new_focus_frame (dpyinfo, 0); + } + +#ifdef HAVE_X_I18N + if (FRAME_XIC (frame)) + XUnsetICFocus (FRAME_XIC (frame)); +#endif + } + + return nr_events; +} + +/* The focus may have changed. Figure out if it is a real focus change, + by checking both FocusIn/Out and Enter/LeaveNotify events. + + Returns number of events inserted into BUFP. */ + +static int +x_detect_focus_change (dpyinfo, event, bufp, numchars) + struct x_display_info *dpyinfo; + XEvent *event; + struct input_event *bufp; + int numchars; +{ + struct frame *frame; + int nr_events = 0; + + frame = x_top_window_to_frame (dpyinfo, event->xany.window); + if (! frame) return nr_events; + + switch (event->type) + { + case EnterNotify: + case LeaveNotify: + if (event->xcrossing.detail != NotifyInferior + && event->xcrossing.focus + && ! (frame->output_data.x->focus_state & FOCUS_EXPLICIT)) + nr_events = x_focus_changed ((event->type == EnterNotify + ? FocusIn : FocusOut), + FOCUS_IMPLICIT, + dpyinfo, + frame, + bufp, + numchars); + break; + + case FocusIn: + case FocusOut: + nr_events = x_focus_changed (event->type, + (event->xfocus.detail == NotifyPointer + ? FOCUS_IMPLICIT : FOCUS_EXPLICIT), + dpyinfo, + frame, + bufp, + numchars); + break; + } + + return nr_events; +} + + /* Handle an event saying the mouse has moved out of an Emacs frame. */ void @@ -10751,15 +10876,16 @@ goto OTHER; #endif - /* Here's a possible interpretation of the whole - FocusIn-EnterNotify FocusOut-LeaveNotify mess. If - you get a FocusIn event, you have to get a FocusOut - event before you relinquish the focus. If you - haven't received a FocusIn event, then a mere - LeaveNotify is enough to free you. */ - case EnterNotify: { + int n; + + n = x_detect_focus_change (dpyinfo, &event, bufp, numchars); + if (n > 0) + { + bufp += n, count += n, numchars -= n; + } + f = x_any_window_to_frame (dpyinfo, event.xcrossing.window); #if 0 @@ -10786,34 +10912,29 @@ } case FocusIn: - f = x_any_window_to_frame (dpyinfo, event.xfocus.window); - if (event.xfocus.detail != NotifyPointer) - dpyinfo->x_focus_event_frame = f; - if (f) { - x_new_focus_frame (dpyinfo, f); - - /* Don't stop displaying the initial startup message - for a switch-frame event we don't need. */ - if (GC_NILP (Vterminal_frame) - && GC_CONSP (Vframe_list) - && !GC_NILP (XCDR (Vframe_list))) + int n; + + n = x_detect_focus_change (dpyinfo, &event, bufp, numchars); + if (n > 0) { - bufp->kind = FOCUS_IN_EVENT; - XSETFRAME (bufp->frame_or_window, f); - bufp->arg = Qnil; - ++bufp, ++count, --numchars; + bufp += n, count += n, numchars -= n; } } -#ifdef HAVE_X_I18N - if (f && FRAME_XIC (f)) - XSetICFocus (FRAME_XIC (f)); -#endif - goto OTHER; case LeaveNotify: + { + int n; + + n = x_detect_focus_change (dpyinfo, &event, bufp, numchars); + if (n > 0) + { + bufp += n, count += n, numchars -= n; + } + } + f = x_top_window_to_frame (dpyinfo, event.xcrossing.window); if (f) { @@ -10841,32 +10962,19 @@ bufp += n, count += n, numchars -= n; } -#if 0 - if (event.xcrossing.focus) - x_mouse_leave (dpyinfo); - else - { - if (f == dpyinfo->x_focus_event_frame) - dpyinfo->x_focus_event_frame = 0; - if (f == dpyinfo->x_focus_frame) - x_new_focus_frame (dpyinfo, 0); - } -#endif } goto OTHER; case FocusOut: - f = x_any_window_to_frame (dpyinfo, event.xfocus.window); - if (event.xfocus.detail != NotifyPointer - && f == dpyinfo->x_focus_event_frame) - dpyinfo->x_focus_event_frame = 0; - if (f && f == dpyinfo->x_focus_frame) - x_new_focus_frame (dpyinfo, 0); - -#ifdef HAVE_X_I18N - if (f && FRAME_XIC (f)) - XUnsetICFocus (FRAME_XIC (f)); -#endif + { + int n; + + n = x_detect_focus_change (dpyinfo, &event, bufp, numchars); + if (n > 0) + { + bufp += n, count += n, numchars -= n; + } + } goto OTHER;