<commit_before>// Copyright (c) 2010 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.

#include "views/controls/menu/native_menu_gtk.h"

#include <algorithm>
#include <map>
#include <string>

#include "app/keyboard_code_conversion_gtk.h"
#include "app/keyboard_codes.h"
#include "app/menus/menu_model.h"
#include "base/i18n/rtl.h"
#include "base/message_loop.h"
#include "base/time.h"
#include "base/utf_string_conversions.h"
#include "gfx/font.h"
#include "gfx/gtk_util.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "views/accelerator.h"
#include "views/controls/menu/menu_2.h"
#include "views/controls/menu/nested_dispatcher_gtk.h"

#if defined(TOUCH_UI)
#include "views/focus/accelerator_handler.h"
#endif

namespace {

const char kPositionString[] = "position";
const char kAccelGroupString[] = "accel_group";

// Key for the property set on the gtk menu that gives the handle to the hosting
// NativeMenuGtk.
const char kNativeMenuGtkString[] = "native_menu_gtk";

// Data passed to the MenuPositionFunc from gtk_menu_popup
struct Position {
  // The point to run the menu at.
  gfx::Point point;
  // The alignment of the menu at that point.
  views::Menu2::Alignment alignment;
};

// Returns true if the menu item type specified can be executed as a command.
bool MenuTypeCanExecute(menus::MenuModel::ItemType type) {
  return type == menus::MenuModel::TYPE_COMMAND ||
      type == menus::MenuModel::TYPE_CHECK ||
      type == menus::MenuModel::TYPE_RADIO;
}

// A callback to gtk_container_foreach to remove all children.
// See |NativeMenuGtk::ResetMenu| for the usage.
void RemoveChildWidget(GtkWidget* widget, gpointer data) {
  GtkWidget* parent = gtk_widget_get_parent(widget);
  gtk_container_remove(GTK_CONTAINER(parent), widget);
}

}  // namespace

namespace views {

////////////////////////////////////////////////////////////////////////////////
// NativeMenuGtk, public:

NativeMenuGtk::NativeMenuGtk(Menu2* menu)
    : parent_(NULL),
      model_(menu->model()),
      menu_(NULL),
      menu_hidden_(true),
      suppress_activate_signal_(false),
      activated_menu_(NULL),
      activated_index_(-1),
      activate_factory_(this),
      host_menu_(menu),
      menu_action_(MENU_ACTION_NONE),
      nested_dispatcher_(NULL),
      ignore_button_release_(true) {
}

NativeMenuGtk::~NativeMenuGtk() {
  if (nested_dispatcher_) {
    // Menu is destroyed while its in message loop.
    // Let nested dispatcher know the creator is deleted.
    nested_dispatcher_->CreatorDestroyed();
  }
  if (menu_) {
    // Don't call MenuDestroyed because menu2 has already been destroyed.
    g_signal_handler_disconnect(menu_, destroy_handler_id_);
    gtk_widget_destroy(menu_);
  }
}

////////////////////////////////////////////////////////////////////////////////
// NativeMenuGtk, MenuWrapper implementation:

void NativeMenuGtk::RunMenuAt(const gfx::Point& point, int alignment) {
  activated_menu_ = NULL;
  activated_index_ = -1;
  menu_action_ = MENU_ACTION_NONE;
  // ignore button release event unless mouse is pressed or moved.
  ignore_button_release_ = true;

  UpdateStates();
  Position position = { point, static_cast<Menu2::Alignment>(alignment) };
  // TODO(beng): value of '1' will not work for context menus!
  gtk_menu_popup(GTK_MENU(menu_), NULL, NULL, MenuPositionFunc, &position, 1,
                 gtk_get_current_event_time());
  DCHECK(menu_hidden_);
  menu_hidden_ = false;

  for (unsigned int i = 0; i < listeners_.size(); ++i) {
    listeners_[i]->OnMenuOpened();
  }

  // Listen for "hide" signal so that we know when to return from the blocking
  // RunMenuAt call.
  gint hide_handle_id =
      g_signal_connect(menu_, "hide", G_CALLBACK(OnMenuHiddenThunk), this);

  gint move_handle_id =
      g_signal_connect(menu_, "move-current",
                       G_CALLBACK(OnMenuMoveCurrentThunk), this);

  // Block until menu is no longer shown by running a nested message loop.
  nested_dispatcher_ = new NestedDispatcherGtk(this, false);
  bool deleted = nested_dispatcher_->RunAndSelfDestruct();
  if (deleted) {
    // The menu was destryed while menu is shown, so return immediately.
    // Don't touch the instance which is already deleted.
    return;
  }
  nested_dispatcher_ = NULL;
  if (!menu_hidden_) {
    // If this happens it means we haven't yet gotten the hide signal and
    // someone else quit the message loop on us.
    NOTREACHED();
    menu_hidden_ = true;
  }

  g_signal_handler_disconnect(G_OBJECT(menu_), hide_handle_id);
  g_signal_handler_disconnect(G_OBJECT(menu_), move_handle_id);

  if (activated_menu_) {
    MessageLoop::current()->PostTask(FROM_HERE,<commit_msg>Fix context menus for touchui=1<commit_after>// Copyright (c) 2010 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.

#include "views/controls/menu/native_menu_gtk.h"

#include <algorithm>
#include <map>
#include <string>

#include "app/keyboard_code_conversion_gtk.h"
#include "app/keyboard_codes.h"
#include "app/menus/menu_model.h"
#include "base/i18n/rtl.h"
#include "base/message_loop.h"
#include "base/time.h"
#include "base/utf_string_conversions.h"
#include "gfx/font.h"
#include "gfx/gtk_util.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "views/accelerator.h"
#include "views/controls/menu/menu_2.h"
#include "views/controls/menu/nested_dispatcher_gtk.h"

#if defined(TOUCH_UI)
#include "views/focus/accelerator_handler.h"
#endif

namespace {

const char kPositionString[] = "position";
const char kAccelGroupString[] = "accel_group";

// Key for the property set on the gtk menu that gives the handle to the hosting
// NativeMenuGtk.
const char kNativeMenuGtkString[] = "native_menu_gtk";

// Data passed to the MenuPositionFunc from gtk_menu_popup
struct Position {
  // The point to run the menu at.
  gfx::Point point;
  // The alignment of the menu at that point.
  views::Menu2::Alignment alignment;
};

// Returns true if the menu item type specified can be executed as a command.
bool MenuTypeCanExecute(menus::MenuModel::ItemType type) {
  return type == menus::MenuModel::TYPE_COMMAND ||
      type == menus::MenuModel::TYPE_CHECK ||
      type == menus::MenuModel::TYPE_RADIO;
}

// A callback to gtk_container_foreach to remove all children.
// See |NativeMenuGtk::ResetMenu| for the usage.
void RemoveChildWidget(GtkWidget* widget, gpointer data) {
  GtkWidget* parent = gtk_widget_get_parent(widget);
  gtk_container_remove(GTK_CONTAINER(parent), widget);
}

}  // namespace

namespace views {

////////////////////////////////////////////////////////////////////////////////
// NativeMenuGtk, public:

NativeMenuGtk::NativeMenuGtk(Menu2* menu)
    : parent_(NULL),
      model_(menu->model()),
      menu_(NULL),
      menu_hidden_(true),
      suppress_activate_signal_(false),
      activated_menu_(NULL),
      activated_index_(-1),
      activate_factory_(this),
      host_menu_(menu),
      menu_action_(MENU_ACTION_NONE),
      nested_dispatcher_(NULL),
      ignore_button_release_(true) {
}

NativeMenuGtk::~NativeMenuGtk() {
  if (nested_dispatcher_) {
    // Menu is destroyed while its in message loop.
    // Let nested dispatcher know the creator is deleted.
    nested_dispatcher_->CreatorDestroyed();
  }
  if (menu_) {
    // Don't call MenuDestroyed because menu2 has already been destroyed.
    g_signal_handler_disconnect(menu_, destroy_handler_id_);
    gtk_widget_destroy(menu_);
  }
}

////////////////////////////////////////////////////////////////////////////////
// NativeMenuGtk, MenuWrapper implementation:

void NativeMenuGtk::RunMenuAt(const gfx::Point& point, int alignment) {
  activated_menu_ = NULL;
  activated_index_ = -1;
  menu_action_ = MENU_ACTION_NONE;
  // ignore button release event unless mouse is pressed or moved.
  ignore_button_release_ = true;

  UpdateStates();
  Position position = { point, static_cast<Menu2::Alignment>(alignment) };
  // TODO(beng): value of '1' will not work for context menus!
  gtk_menu_popup(GTK_MENU(menu_), NULL, NULL, MenuPositionFunc, &position, 1,
                 gtk_get_current_event_time());
  DCHECK(menu_hidden_);
  menu_hidden_ = false;

  for (unsigned int i = 0; i < listeners_.size(); ++i) {
    listeners_[i]->OnMenuOpened();
  }

  // Listen for "hide" signal so that we know when to return from the blocking
  // RunMenuAt call.
  gint hide_handle_id =
      g_signal_connect(menu_, "hide", G_CALLBACK(OnMenuHiddenThunk), this);

  gint move_handle_id =
      g_signal_connect(menu_, "move-current",
                       G_CALLBACK(OnMenuMoveCurrentThunk), this);

  // Block until menu is no longer shown by running a nested message loop.
  nested_dispatcher_ = new NestedDispatcherGtk(this, true);
  bool deleted = nested_dispatcher_->RunAndSelfDestruct();
  if (deleted) {
    // The menu was destryed while menu is shown, so return immediately.
    // Don't touch the instance which is already deleted.
    return;
  }
  nested_dispatcher_ = NULL;
  if (!menu_hidden_) {
    // If this happens it means we haven't yet gotten the hide signal and
    // someone else quit the message loop on us.
    NOTREACHED();
    menu_hidden_ = true;
  }

  g_signal_handler_disconnect(G_OBJECT(menu_), hide_handle_id);
  g_signal_handler_disconnect(G_OBJECT(menu_), move_handle_id);

  if (activated_menu_) {
    MessageLoop::current()->PostTask(FROM_HERE,
{'fraction_non_alphanumeric': 0.13747251596691445, 'fraction_numerical': 0.0034551355878965555, 'mean_word_length': 3.5464064731080436, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6945656', 'n_tokens_mistral': 3007, 'n_tokens_neox': 2937, 'n_words': 787}