+/* 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;
+}
+
+