<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// TODO(yusukes): Remove the #if once the ARM bot (crbug.com/84694) is fixed.
#if defined(HAVE_XINPUT2)

#include "chrome/browser/chromeos/xinput_hierarchy_changed_event_listener.h"

#include <gdk/gdkx.h>
#include <X11/Xlib.h>
#include <X11/extensions/XInput2.h>

#include "chrome/browser/chromeos/input_method/xkeyboard.h"

namespace {

// Gets the major opcode for XInput2. Returns -1 on error.
int GetXInputOpCode() {
  static const char kExtensionName[] = "XInputExtension";
  int xi_opcode = -1;
  int event;
  int error;

  Display* display = MessageLoopForUI::current()->GetDisplay();
  if (!XQueryExtension(display, kExtensionName, &xi_opcode, &event, &error)) {
    VLOG(1) << "X Input extension not available: error=" << error;
    return -1;
  }
  return xi_opcode;
}

// Starts listening to the XI_HierarchyChanged events.
void SelectXInputEvents() {
  XIEventMask evmask;
  unsigned char mask[XIMaskLen(XI_LASTEVENT)] = {0};
  XISetMask(mask, XI_HierarchyChanged);

  evmask.deviceid = XIAllDevices;
  evmask.mask_len = sizeof(mask);
  evmask.mask = mask;

  Display* display = MessageLoopForUI::current()->GetDisplay();
  XISelectEvents(display, DefaultRootWindow(display), &evmask, 1);
}

// Checks the |event| and asynchronously sets the XKB layout when necessary.
void HandleHierarchyChangedEvent(XIHierarchyEvent* event) {
  for (int i = 0; i < event->num_info; ++i) {
    XIHierarchyInfo* info = &event->info[i];
    if ((event->flags & XISlaveAdded) &&
        (info->use == XIFloatingSlave) &&
        (info->flags & XISlaveAdded)) {
      chromeos::input_method::ReapplyCurrentKeyboardLayout();
      break;
    }
  }
}

}  // namespace

namespace chromeos {

// static
XInputHierarchyChangedEventListener*
XInputHierarchyChangedEventListener::GetInstance() {
  return Singleton<XInputHierarchyChangedEventListener>::get();
}

XInputHierarchyChangedEventListener::XInputHierarchyChangedEventListener()
    : stopped_(false),
      xiopcode_(GetXInputOpCode()) {
  SelectXInputEvents();

#if defined(TOUCH_UI)
  MessageLoopForUI::current()->AddObserver(this);
#else
  gdk_window_add_filter(NULL, GdkEventFilter, this);
#endif
}

XInputHierarchyChangedEventListener::~XInputHierarchyChangedEventListener() {
  Stop();
}

void XInputHierarchyChangedEventListener::Stop() {
  if (stopped_)
    return;

#if defined(TOUCH_UI)
  MessageLoopForUI::current()->RemoveObserver(this);
#else
  gdk_window_remove_filter(NULL, GdkEventFilter, this);
#endif
  stopped_ = true;
  xiopcode_ = -1;
}

// static
GdkFilterReturn XInputHierarchyChangedEventListener::GdkEventFilter(
    GdkXEvent* gxevent, GdkEvent* gevent, gpointer data) {
  XInputHierarchyChangedEventListener* listener =
      static_cast<XInputHierarchyChangedEventListener*>(data);
  XEvent* xevent = static_cast<XEvent*>(gxevent);

  return listener->WillProcessXEvent(xevent) ? GDK_FILTER_REMOVE
                                             : GDK_FILTER_CONTINUE;
}

bool XInputHierarchyChangedEventListener::WillProcessXEvent(XEvent* xevent) {
  if ((xevent->xcookie.type != GenericEvent) ||
      (xevent->xcookie.extension != xiopcode_)) {
    return false;
  }
  if (!XGetEventData(xevent->xgeneric.display, &xevent->xcookie)) {
    VLOG(1) << "XGetEventData failed";
    return false;
  }

  XGenericEventCookie* cookie = &(xevent->xcookie);
  const bool should_consume = (cookie->evtype == XI_HierarchyChanged);
  if (should_consume) {
    HandleHierarchyChangedEvent(static_cast<XIHierarchyEvent*>(cookie->data));
  }
  XFreeEventData(xevent->xgeneric.display, cookie);

  return should_consume;
}

}  // namespace chromeos

#endif<commit_msg>Abort chromeos-chrome build if HAVE_XINPUT2 macro is not defined on x86.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// TODO(yusukes): Remove the #if once the ARM bot (crbug.com/84694) is fixed.
#if defined(HAVE_XINPUT2)

#include "chrome/browser/chromeos/xinput_hierarchy_changed_event_listener.h"

#include <gdk/gdkx.h>
#include <X11/Xlib.h>
#include <X11/extensions/XInput2.h>

#include "chrome/browser/chromeos/input_method/xkeyboard.h"

namespace {

// Gets the major opcode for XInput2. Returns -1 on error.
int GetXInputOpCode() {
  static const char kExtensionName[] = "XInputExtension";
  int xi_opcode = -1;
  int event;
  int error;

  Display* display = MessageLoopForUI::current()->GetDisplay();
  if (!XQueryExtension(display, kExtensionName, &xi_opcode, &event, &error)) {
    VLOG(1) << "X Input extension not available: error=" << error;
    return -1;
  }
  return xi_opcode;
}

// Starts listening to the XI_HierarchyChanged events.
void SelectXInputEvents() {
  XIEventMask evmask;
  unsigned char mask[XIMaskLen(XI_LASTEVENT)] = {0};
  XISetMask(mask, XI_HierarchyChanged);

  evmask.deviceid = XIAllDevices;
  evmask.mask_len = sizeof(mask);
  evmask.mask = mask;

  Display* display = MessageLoopForUI::current()->GetDisplay();
  XISelectEvents(display, DefaultRootWindow(display), &evmask, 1);
}

// Checks the |event| and asynchronously sets the XKB layout when necessary.
void HandleHierarchyChangedEvent(XIHierarchyEvent* event) {
  for (int i = 0; i < event->num_info; ++i) {
    XIHierarchyInfo* info = &event->info[i];
    if ((event->flags & XISlaveAdded) &&
        (info->use == XIFloatingSlave) &&
        (info->flags & XISlaveAdded)) {
      chromeos::input_method::ReapplyCurrentKeyboardLayout();
      break;
    }
  }
}

}  // namespace

namespace chromeos {

// static
XInputHierarchyChangedEventListener*
XInputHierarchyChangedEventListener::GetInstance() {
  return Singleton<XInputHierarchyChangedEventListener>::get();
}

XInputHierarchyChangedEventListener::XInputHierarchyChangedEventListener()
    : stopped_(false),
      xiopcode_(GetXInputOpCode()) {
  SelectXInputEvents();

#if defined(TOUCH_UI)
  MessageLoopForUI::current()->AddObserver(this);
#else
  gdk_window_add_filter(NULL, GdkEventFilter, this);
#endif
}

XInputHierarchyChangedEventListener::~XInputHierarchyChangedEventListener() {
  Stop();
}

void XInputHierarchyChangedEventListener::Stop() {
  if (stopped_)
    return;

#if defined(TOUCH_UI)
  MessageLoopForUI::current()->RemoveObserver(this);
#else
  gdk_window_remove_filter(NULL, GdkEventFilter, this);
#endif
  stopped_ = true;
  xiopcode_ = -1;
}

// static
GdkFilterReturn XInputHierarchyChangedEventListener::GdkEventFilter(
    GdkXEvent* gxevent, GdkEvent* gevent, gpointer data) {
  XInputHierarchyChangedEventListener* listener =
      static_cast<XInputHierarchyChangedEventListener*>(data);
  XEvent* xevent = static_cast<XEvent*>(gxevent);

  return listener->WillProcessXEvent(xevent) ? GDK_FILTER_REMOVE
                                             : GDK_FILTER_CONTINUE;
}

bool XInputHierarchyChangedEventListener::WillProcessXEvent(XEvent* xevent) {
  if ((xevent->xcookie.type != GenericEvent) ||
      (xevent->xcookie.extension != xiopcode_)) {
    return false;
  }
  if (!XGetEventData(xevent->xgeneric.display, &xevent->xcookie)) {
    VLOG(1) << "XGetEventData failed";
    return false;
  }

  XGenericEventCookie* cookie = &(xevent->xcookie);
  const bool should_consume = (cookie->evtype == XI_HierarchyChanged);
  if (should_consume) {
    HandleHierarchyChangedEvent(static_cast<XIHierarchyEvent*>(cookie->data));
  }
  XFreeEventData(xevent->xgeneric.display, cookie);

  return should_consume;
}

}  // namespace chromeos

#endif

// TODO(yusukes): Remove this check when crbug.com/84694 is resolved.
#if defined(ARCH_CPU_X86_FAMILY) && !defined(HAVE_XINPUT2)
#error XINPUT2 should always be enabled on Chrome OS x86!
#endif
{'fraction_non_alphanumeric': 0.11922295581513459, 'fraction_numerical': 0.008125952260030472, 'mean_word_length': 4.8132841328413285, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4823808', 'n_tokens_mistral': 2640, 'n_tokens_neox': 2589, 'n_words': 539}