<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 <gtk/gtk.h>

#include "build/build_config.h"

#include "app/l10n_util.h"
#include "base/i18n/rtl.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/certificate_viewer.h"
#include "chrome/browser/gtk/browser_toolbar_gtk.h"
#include "chrome/browser/gtk/browser_window_gtk.h"
#include "chrome/browser/gtk/gtk_chrome_link_button.h"
#include "chrome/browser/gtk/gtk_theme_provider.h"
#include "chrome/browser/gtk/gtk_util.h"
#include "chrome/browser/gtk/info_bubble_gtk.h"
#include "chrome/browser/gtk/location_bar_view_gtk.h"
#include "chrome/browser/page_info_model.h"
#include "chrome/browser/page_info_window.h"
#include "chrome/common/notification_observer.h"
#include "chrome/common/notification_registrar.h"
#include "chrome/common/notification_service.h"
#include "gfx/gtk_util.h"
#include "googleurl/src/gurl.h"
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"

class Profile;

namespace {

class PageInfoBubbleGtk : public PageInfoModel::PageInfoModelObserver,
                          public InfoBubbleGtkDelegate,
                          public NotificationObserver {
 public:
  PageInfoBubbleGtk(gfx::NativeWindow parent,
                    Profile* profile,
                    const GURL& url,
                    const NavigationEntry::SSLStatus& ssl,
                    bool show_history);
  virtual ~PageInfoBubbleGtk();

  // PageInfoModelObserver implementation:
  virtual void ModelChanged();

  // NotificationObserver implementation:
  virtual void Observe(NotificationType type,
                       const NotificationSource& source,
                       const NotificationDetails& details);

  // InfoBubbleGtkDelegate implementation:
  virtual void InfoBubbleClosing(InfoBubbleGtk* info_bubble,
                                 bool closed_by_escape);

 private:
  // Layouts the different sections retrieved from the model.
  void InitContents();

  // Returns a widget that contains the UI for the passed |section|.
  GtkWidget* CreateSection(const PageInfoModel::SectionInfo& section);

  // Link button callbacks.
  CHROMEGTK_CALLBACK_0(PageInfoBubbleGtk, void, OnViewCertLinkClicked);
  CHROMEGTK_CALLBACK_0(PageInfoBubbleGtk, void, OnHelpLinkClicked);

  // The model containing the different sections to display.
  PageInfoModel model_;

  // The url for this dialog. Should be unique among active dialogs.
  GURL url_;

  // The id of the certificate for this page.
  int cert_id_;

  // Parent window.
  GtkWindow* parent_;

  // The virtual box containing the sections.
  GtkWidget* contents_;

  // The widget relative to which we are positioned.
  GtkWidget* anchor_;

  // Provides colors and stuff.
  GtkThemeProvider* theme_provider_;

  // The various elements in the interface we keep track of for theme changes.
  std::vector<GtkWidget*> labels_;
  std::vector<GtkWidget*> links_;

  InfoBubbleGtk* bubble_;

  NotificationRegistrar registrar_;

  DISALLOW_COPY_AND_ASSIGN(PageInfoBubbleGtk);
};

PageInfoBubbleGtk::PageInfoBubbleGtk(gfx::NativeWindow parent,
                                     Profile* profile,
                                     const GURL& url,
                                     const NavigationEntry::SSLStatus& ssl,
                                     bool show_history)
    : ALLOW_THIS_IN_INITIALIZER_LIST(model_(profile, url, ssl,
                                            show_history, this)),
      url_(url),
      cert_id_(ssl.cert_id()),
      parent_(parent),
      contents_(NULL),
      theme_provider_(GtkThemeProvider::GetFrom(profile)) {
  BrowserWindowGtk* browser_window =
      BrowserWindowGtk::GetBrowserWindowForNativeWindow(parent);

  anchor_ = browser_window->
      GetToolbar()->GetLocationBarView()->location_icon_widget();

  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
                 NotificationService::AllSources());

  InitContents();

  InfoBubbleGtk::ArrowLocationGtk arrow_location = base::i18n::IsRTL() ?
      InfoBubbleGtk::ARROW_LOCATION_TOP_RIGHT :
      InfoBubbleGtk::ARROW_LOCATION_TOP_LEFT;
  bubble_ = InfoBubbleGtk::Show(anchor_,
                                NULL,  // |rect|
                                contents_,
                                arrow_location,
                                true,  // |match_system_theme|
                                true,  // |grab_input|
                                theme_provider_,
                                this);  // |delegate|
  if (!bubble_) {
    NOTREACHED();
    return;
  }
}

PageInfoBubbleGtk::~PageInfoBubbleGtk() {
}

void PageInfoBubbleGtk::ModelChanged() {
  InitContents();
}

void PageInfoBubbleGtk::Observe(NotificationType type,
                                const NotificationSource& source,
                                const NotificationDetails& details) {
  DCHECK(type == NotificationType::BROWSER_THEME_CHANGED);

  for (std::vector<GtkWidget*>::iterator it = links_.begin();
       it != links_.end(); ++it) {
    gtk_chrome_link_button_set_use_gtk_theme(
        GTK_CHROME_LINK_BUTTON(*it),
        theme_provider_->UseGtkTheme());
  }

  if (theme_provider_->UseGtkTheme()) {
    for (std::vector<GtkWidget*>::iterator it = labels_.begin();
         it != labels_.end(); ++it) {
      gtk_widget_modify_fg(*it, GTK_STATE_NORMAL, NULL);
    }
  } else {
    for (std::vector<GtkWidget*>::iterator it = labels_.begin();
         it != labels_.end(); ++it) {
      gtk_widget_modify_fg(*it, GTK_STATE_NORMAL, &gfx::kGdkBlack);
    }
  }
}

void PageInfoBubbleGtk::InfoBubbleClosing(InfoBubbleGtk* info_bubble,
                                          bool closed_by_escape) {
  delete this;
}

void PageInfoBubbleGtk::InitContents() {
  if (!contents_) {
    contents_ = gtk_vbox_new(FALSE, gtk_util::kContentAreaSpacing);
    gtk_container_set_border_width(GTK_CONTAINER(contents_),
                                   gtk_util::kContentAreaBorder);
  } else {
    labels_.clear();
    links_.clear();
    gtk_util::RemoveAllChildren(contents_);
  }

  for (int i = 0; i < model_.GetSectionCount(); i++) {
    gtk_box_pack_start(GTK_BOX(contents_),
                       CreateSection(model_.GetSectionInfo(i)),
                       FALSE, FALSE, 0);
    gtk_box_pack_start(GTK_BOX(contents_),
                       gtk_hseparator_new(),
                       FALSE, FALSE, 0);
  }

  GtkWidget* help_link = gtk_chrome_link_button_new(
      l10n_util::GetStringUTF8(IDS_PAGE_INFO_HELP_CENTER_LINK).c_str());
  links_.push_back(help_link);
  GtkWidget* help_link_hbox = gtk_hbox_new(FALSE, 0);
  // Stick it in an hbox so it doesn't expand to the whole width.
  gtk_box_pack_start(GTK_BOX(help_link_hbox), help_link, TRUE, FALSE, 0);
  gtk_box_pack_start(GTK_BOX(contents_), help_link_hbox, FALSE, FALSE, 0);
  g_signal_connect(help_link, "clicked",
                   G_CALLBACK(OnHelpLinkClickedThunk), this);

  theme_provider_->InitThemesFor(this);
  gtk_widget_show_all(contents_);
}

GtkWidget* PageInfoBubbleGtk::CreateSection(
    const PageInfoModel::SectionInfo& section) {
  GtkWidget* section_box = gtk_hbox_new(FALSE, 0);

  GdkPixbuf* pixbuf = model_.GetIconImage(section.icon_id);
  if (pixbuf) {
    GtkWidget* image = gtk_image_new_from_pixbuf(pixbuf);
    gtk_box_pack_start(GTK_BOX(section_box), image, FALSE, FALSE,
                       gtk_util::kControlSpacing);
    gtk_misc_set_alignment(GTK_MISC(image), 0, 0);
  }

  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
  gtk_box_pack_start(GTK_BOX(section_box), vbox, TRUE, TRUE, 0);

  if (!section.headline.empty()) {
    GtkWidget* label = gtk_label_new(UTF16ToUTF8(section.headline).c_str());
    labels_.push_back(label);
    PangoAttrList* attributes = pango_attr_list_new();
    pango_attr_list_insert(attributes,
                           pango_attr_weight_new(PANGO_WEIGHT_BOLD));
    gtk_label_set_attributes(GTK_LABEL(label), attributes);
    pango_attr_list_unref(attributes);
    gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
    // Allow linebreaking in the middle of words if necessary, so that extremely
    // long hostnames (longer than one line) will still be completely shown.
    gtk_label_set_line_wrap_mode(GTK_LABEL(label), PANGO_WRAP_WORD_CHAR);
    gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
    gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
    gtk_widget_set_size_request(label, 400, -1);
  }
  GtkWidget* label = gtk_label_new(UTF16ToUTF8(section.description).c_str());
  labels_.push_back(label);
  gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
  gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
  // Allow linebreaking in the middle of words if necessary, so that extremely
  // long hostnames (longer than one line) will still be completely shown.
  gtk_label_set_line_wrap_mode(GTK_LABEL(label), PANGO_WRAP_WORD_CHAR);
  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
  gtk_widget_set_size_request(label, 400, -1);

  if (section.type == PageInfoModel::SECTION_INFO_IDENTITY && cert_id_ > 0) {
    GtkWidget* view_cert_link = gtk_chrome_link_button_new(
        l10n_util::GetStringUTF8(IDS_PAGEINFO_CERT_INFO_BUTTON).c_str());
    links_.push_back(view_cert_link);
    GtkWidget* cert_link_hbox = gtk_hbox_new(FALSE, 0);
    // Stick it in an hbox so it doesn't expand to the whole width.
    gtk_box_pack_start(GTK_BOX(cert_link_hbox), view_cert_link,
                       FALSE, FALSE, 0);
    gtk_box_pack_start(GTK_BOX(vbox), cert_link_hbox, FALSE, FALSE, 0);
    g_signal_connect(view_cert_link, "clicked",
                     G_CALLBACK(OnViewCertLinkClickedThunk), this);
  }

  return section_box;
}

void PageInfoBubbleGtk::OnViewCertLinkClicked(GtkWidget* widget) {
  ShowCertificateViewerByID(GTK_WINDOW(parent_), cert_id_);
  bubble_->Close();
}

void PageInfoBubbleGtk::OnHelpLinkClicked(GtkWidget* widget) {
  GURL url = GURL(l10n_util::GetStringUTF16(IDS_PAGE_INFO_HELP_CENTER));
  Browser* browser = BrowserList::GetLastActive();
  browser->OpenURL(url, GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK);
  bubble_->Close();
}

}  // namespace

namespace browser {

void ShowPageInfoBubble(gfx::NativeWindow parent,
                        Profile* profile,
                        const GURL& url,
                        const NavigationEntry::SSLStatus& ssl,
                        bool show_history) {
  new PageInfoBubbleGtk(parent, profile, url, ssl, show_history);
}

}  // namespace browser
<commit_msg>Gtk page info bubble: left align the help link.<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 <gtk/gtk.h>

#include "build/build_config.h"

#include "app/l10n_util.h"
#include "base/i18n/rtl.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/certificate_viewer.h"
#include "chrome/browser/gtk/browser_toolbar_gtk.h"
#include "chrome/browser/gtk/browser_window_gtk.h"
#include "chrome/browser/gtk/gtk_chrome_link_button.h"
#include "chrome/browser/gtk/gtk_theme_provider.h"
#include "chrome/browser/gtk/gtk_util.h"
#include "chrome/browser/gtk/info_bubble_gtk.h"
#include "chrome/browser/gtk/location_bar_view_gtk.h"
#include "chrome/browser/page_info_model.h"
#include "chrome/browser/page_info_window.h"
#include "chrome/common/notification_observer.h"
#include "chrome/common/notification_registrar.h"
#include "chrome/common/notification_service.h"
#include "gfx/gtk_util.h"
#include "googleurl/src/gurl.h"
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"

class Profile;

namespace {

class PageInfoBubbleGtk : public PageInfoModel::PageInfoModelObserver,
                          public InfoBubbleGtkDelegate,
                          public NotificationObserver {
 public:
  PageInfoBubbleGtk(gfx::NativeWindow parent,
                    Profile* profile,
                    const GURL& url,
                    const NavigationEntry::SSLStatus& ssl,
                    bool show_history);
  virtual ~PageInfoBubbleGtk();

  // PageInfoModelObserver implementation:
  virtual void ModelChanged();

  // NotificationObserver implementation:
  virtual void Observe(NotificationType type,
                       const NotificationSource& source,
                       const NotificationDetails& details);

  // InfoBubbleGtkDelegate implementation:
  virtual void InfoBubbleClosing(InfoBubbleGtk* info_bubble,
                                 bool closed_by_escape);

 private:
  // Layouts the different sections retrieved from the model.
  void InitContents();

  // Returns a widget that contains the UI for the passed |section|.
  GtkWidget* CreateSection(const PageInfoModel::SectionInfo& section);

  // Link button callbacks.
  CHROMEGTK_CALLBACK_0(PageInfoBubbleGtk, void, OnViewCertLinkClicked);
  CHROMEGTK_CALLBACK_0(PageInfoBubbleGtk, void, OnHelpLinkClicked);

  // The model containing the different sections to display.
  PageInfoModel model_;

  // The url for this dialog. Should be unique among active dialogs.
  GURL url_;

  // The id of the certificate for this page.
  int cert_id_;

  // Parent window.
  GtkWindow* parent_;

  // The virtual box containing the sections.
  GtkWidget* contents_;

  // The widget relative to which we are positioned.
  GtkWidget* anchor_;

  // Provides colors and stuff.
  GtkThemeProvider* theme_provider_;

  // The various elements in the interface we keep track of for theme changes.
  std::vector<GtkWidget*> labels_;
  std::vector<GtkWidget*> links_;

  InfoBubbleGtk* bubble_;

  NotificationRegistrar registrar_;

  DISALLOW_COPY_AND_ASSIGN(PageInfoBubbleGtk);
};

PageInfoBubbleGtk::PageInfoBubbleGtk(gfx::NativeWindow parent,
                                     Profile* profile,
                                     const GURL& url,
                                     const NavigationEntry::SSLStatus& ssl,
                                     bool show_history)
    : ALLOW_THIS_IN_INITIALIZER_LIST(model_(profile, url, ssl,
                                            show_history, this)),
      url_(url),
      cert_id_(ssl.cert_id()),
      parent_(parent),
      contents_(NULL),
      theme_provider_(GtkThemeProvider::GetFrom(profile)) {
  BrowserWindowGtk* browser_window =
      BrowserWindowGtk::GetBrowserWindowForNativeWindow(parent);

  anchor_ = browser_window->
      GetToolbar()->GetLocationBarView()->location_icon_widget();

  registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
                 NotificationService::AllSources());

  InitContents();

  InfoBubbleGtk::ArrowLocationGtk arrow_location = base::i18n::IsRTL() ?
      InfoBubbleGtk::ARROW_LOCATION_TOP_RIGHT :
      InfoBubbleGtk::ARROW_LOCATION_TOP_LEFT;
  bubble_ = InfoBubbleGtk::Show(anchor_,
                                NULL,  // |rect|
                                contents_,
                                arrow_location,
                                true,  // |match_system_theme|
                                true,  // |grab_input|
                                theme_provider_,
                                this);  // |delegate|
  if (!bubble_) {
    NOTREACHED();
    return;
  }
}

PageInfoBubbleGtk::~PageInfoBubbleGtk() {
}

void PageInfoBubbleGtk::ModelChanged() {
  InitContents();
}

void PageInfoBubbleGtk::Observe(NotificationType type,
                                const NotificationSource& source,
                                const NotificationDetails& details) {
  DCHECK(type == NotificationType::BROWSER_THEME_CHANGED);

  for (std::vector<GtkWidget*>::iterator it = links_.begin();
       it != links_.end(); ++it) {
    gtk_chrome_link_button_set_use_gtk_theme(
        GTK_CHROME_LINK_BUTTON(*it),
        theme_provider_->UseGtkTheme());
  }

  if (theme_provider_->UseGtkTheme()) {
    for (std::vector<GtkWidget*>::iterator it = labels_.begin();
         it != labels_.end(); ++it) {
      gtk_widget_modify_fg(*it, GTK_STATE_NORMAL, NULL);
    }
  } else {
    for (std::vector<GtkWidget*>::iterator it = labels_.begin();
         it != labels_.end(); ++it) {
      gtk_widget_modify_fg(*it, GTK_STATE_NORMAL, &gfx::kGdkBlack);
    }
  }
}

void PageInfoBubbleGtk::InfoBubbleClosing(InfoBubbleGtk* info_bubble,
                                          bool closed_by_escape) {
  delete this;
}

void PageInfoBubbleGtk::InitContents() {
  if (!contents_) {
    contents_ = gtk_vbox_new(FALSE, gtk_util::kContentAreaSpacing);
    gtk_container_set_border_width(GTK_CONTAINER(contents_),
                                   gtk_util::kContentAreaBorder);
  } else {
    labels_.clear();
    links_.clear();
    gtk_util::RemoveAllChildren(contents_);
  }

  for (int i = 0; i < model_.GetSectionCount(); i++) {
    gtk_box_pack_start(GTK_BOX(contents_),
                       CreateSection(model_.GetSectionInfo(i)),
                       FALSE, FALSE, 0);
    gtk_box_pack_start(GTK_BOX(contents_),
                       gtk_hseparator_new(),
                       FALSE, FALSE, 0);
  }

  GtkWidget* help_link = gtk_chrome_link_button_new(
      l10n_util::GetStringUTF8(IDS_PAGE_INFO_HELP_CENTER_LINK).c_str());
  links_.push_back(help_link);
  GtkWidget* help_link_hbox = gtk_hbox_new(FALSE, 0);
  // Stick it in an hbox so it doesn't expand to the whole width.
  gtk_box_pack_start(GTK_BOX(help_link_hbox), help_link, FALSE, FALSE, 0);
  gtk_box_pack_start(GTK_BOX(contents_), help_link_hbox, FALSE, FALSE, 0);
  g_signal_connect(help_link, "clicked",
                   G_CALLBACK(OnHelpLinkClickedThunk), this);

  theme_provider_->InitThemesFor(this);
  gtk_widget_show_all(contents_);
}

GtkWidget* PageInfoBubbleGtk::CreateSection(
    const PageInfoModel::SectionInfo& section) {
  GtkWidget* section_box = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);

  GdkPixbuf* pixbuf = model_.GetIconImage(section.icon_id);
  if (pixbuf) {
    GtkWidget* image = gtk_image_new_from_pixbuf(pixbuf);
    gtk_box_pack_start(GTK_BOX(section_box), image, FALSE, FALSE, 0);
    gtk_misc_set_alignment(GTK_MISC(image), 0, 0);
  }

  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
  gtk_box_pack_start(GTK_BOX(section_box), vbox, TRUE, TRUE, 0);

  if (!section.headline.empty()) {
    GtkWidget* label = gtk_label_new(UTF16ToUTF8(section.headline).c_str());
    labels_.push_back(label);
    PangoAttrList* attributes = pango_attr_list_new();
    pango_attr_list_insert(attributes,
                           pango_attr_weight_new(PANGO_WEIGHT_BOLD));
    gtk_label_set_attributes(GTK_LABEL(label), attributes);
    pango_attr_list_unref(attributes);
    gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
    // Allow linebreaking in the middle of words if necessary, so that extremely
    // long hostnames (longer than one line) will still be completely shown.
    gtk_label_set_line_wrap_mode(GTK_LABEL(label), PANGO_WRAP_WORD_CHAR);
    gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
    gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
    gtk_widget_set_size_request(label, 400, -1);
  }
  GtkWidget* label = gtk_label_new(UTF16ToUTF8(section.description).c_str());
  labels_.push_back(label);
  gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
  gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
  // Allow linebreaking in the middle of words if necessary, so that extremely
  // long hostnames (longer than one line) will still be completely shown.
  gtk_label_set_line_wrap_mode(GTK_LABEL(label), PANGO_WRAP_WORD_CHAR);
  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
  gtk_widget_set_size_request(label, 400, -1);

  if (section.type == PageInfoModel::SECTION_INFO_IDENTITY && cert_id_ > 0) {
    GtkWidget* view_cert_link = gtk_chrome_link_button_new(
        l10n_util::GetStringUTF8(IDS_PAGEINFO_CERT_INFO_BUTTON).c_str());
    links_.push_back(view_cert_link);
    GtkWidget* cert_link_hbox = gtk_hbox_new(FALSE, 0);
    // Stick it in an hbox so it doesn't expand to the whole width.
    gtk_box_pack_start(GTK_BOX(cert_link_hbox), view_cert_link,
                       FALSE, FALSE, 0);
    gtk_box_pack_start(GTK_BOX(vbox), cert_link_hbox, FALSE, FALSE, 0);
    g_signal_connect(view_cert_link, "clicked",
                     G_CALLBACK(OnViewCertLinkClickedThunk), this);
  }

  return section_box;
}

void PageInfoBubbleGtk::OnViewCertLinkClicked(GtkWidget* widget) {
  ShowCertificateViewerByID(GTK_WINDOW(parent_), cert_id_);
  bubble_->Close();
}

void PageInfoBubbleGtk::OnHelpLinkClicked(GtkWidget* widget) {
  GURL url = GURL(l10n_util::GetStringUTF16(IDS_PAGE_INFO_HELP_CENTER));
  Browser* browser = BrowserList::GetLastActive();
  browser->OpenURL(url, GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK);
  bubble_->Close();
}

}  // namespace

namespace browser {

void ShowPageInfoBubble(gfx::NativeWindow parent,
                        Profile* profile,
                        const GURL& url,
                        const NavigationEntry::SSLStatus& ssl,
                        bool show_history) {
  new PageInfoBubbleGtk(parent, profile, url, ssl, show_history);
}

}  // namespace browser
<|endoftext|>


<commit_before><commit_msg>Also need to set aura::Window title<commit_after><|endoftext|>


<commit_before>#include "utils.h"

using namespace std;
using namespace Eigen;

/* Try splitting over all whitespaces not just space */
vector<string> split_line(const string& line, char delim) {
  vector<string> words;
  stringstream ss(line);
  string item;
  while (std::getline(ss, item, delim)) {
    if (!item.empty())
      words.push_back(item);
  }
  return words;
}

void ReadVecsFromFile(const string& vec_file_name, mapStrUnsigned* t_vocab,
                      vector<Col>* word_vecs) {
  ifstream vec_file(vec_file_name.c_str());
  mapStrUnsigned& vocab = *t_vocab;
  unsigned vocab_size = 0;
  if (vec_file.is_open()) {
    string line;
    vocab.clear();
    while (getline(vec_file, line)) {
      vector<string> vector_stuff = split_line(line, ' ');
      string word = vector_stuff[0];
      Col word_vec = Col::Zero(vector_stuff.size()-1);
      for (unsigned i = 0; i < word_vec.size(); ++i)
        word_vec(i, 0) = stof(vector_stuff[i+1]);
      vocab[word] = vocab_size++;
      word_vecs->push_back(word_vec);
    }
    cerr << "Read: " << vec_file_name << endl;
    cerr << "Vocab length: " << word_vecs->size() << endl;
    cerr << "Vector length: " << (*word_vecs)[0].size() << endl << endl;
    vec_file.close();

    assert (word_vecs->size() == vocab.size());
  } else {
    cerr << "Could not open " << vec_file;
    exit(0);
  }
}

void ReadVecsFromFile(const string& vec_file_name, mapUnsignedStr* t_vocab,
                      vector<Col>* word_vecs) {
  ifstream vec_file(vec_file_name.c_str());
  mapUnsignedStr& vocab = *t_vocab;
  unsigned vocab_size = 0;
  if (vec_file.is_open()) {
    string line;
    vocab.clear();
    while (getline(vec_file, line)) {
      vector<string> vector_stuff = split_line(line, ' ');
      string word = vector_stuff[0];
      Col word_vec = Col::Zero(vector_stuff.size()-1);
      for (unsigned i = 0; i < word_vec.size(); ++i)
        word_vec(i, 0) = stof(vector_stuff[i+1]);
      vocab[vocab_size++] = word;
      word_vecs->push_back(word_vec);
    }
    cerr << "Read: " << vec_file_name << endl;
    cerr << "Vocab length: " << word_vecs->size() << endl;
    cerr << "Vector length: " << (*word_vecs)[0].size() << endl << endl;
    vec_file.close();

    assert (word_vecs->size() == vocab.size());
  } else {
    cerr << "Could not open " << vec_file;
    exit(0);
  }
}

void ElemwiseTanh(Col* v) {
  for (unsigned i = 0; i < v->rows(); ++i)
    (*v)(i, 0) = tanh((*v)(i, 0));
}

/* v is the vector after taking tanh() */
void ElemwiseTanhGrad(const Col &v, Col* g) {
  for (int i = 0; i < v.rows(); ++i)
    (*g)(i, 0) = 1 - pow(v(i, 0), 2);
}

void ElemwiseAndrewNsnl(Col *v) {
  for (int i = 0; i < v->rows(); ++i) {
    double x = (*v)(i, 0);
    if (x) {
      bool flag = (x < 0);
      double y_n = flag ? -x : x;
      for (unsigned i = 0; i < 12; ++i) {
        const double sq = y_n * y_n;
        y_n = (2 * sq * y_n / 3 + x) / (sq + 1);
      }
      (*v)(i, 0) = flag ? -y_n : y_n;
    }
  }
}

void ElemwiseAndrewNsnlGrad(const Col &v, Col* g) {
  for (int i = 0; i < v.rows(); ++i)
    (*g)(i, 0) = 1 / (1 + pow(v(i, 0), 2));
}

double CosineSim(const Col& ci, const Col& cj) {
  return ci.dot(cj)/sqrt(ci.squaredNorm() * cj.squaredNorm());
}
<commit_msg>Correcting the file name from vec_file to vec_file_name<commit_after>#include "utils.h"

using namespace std;
using namespace Eigen;

/* Try splitting over all whitespaces not just space */
vector<string> split_line(const string& line, char delim) {
  vector<string> words;
  stringstream ss(line);
  string item;
  while (std::getline(ss, item, delim)) {
    if (!item.empty())
      words.push_back(item);
  }
  return words;
}

void ReadVecsFromFile(const string& vec_file_name, mapStrUnsigned* t_vocab,
                      vector<Col>* word_vecs) {
  ifstream vec_file(vec_file_name.c_str());
  mapStrUnsigned& vocab = *t_vocab;
  unsigned vocab_size = 0;
  if (vec_file.is_open()) {
    string line;
    vocab.clear();
    while (getline(vec_file, line)) {
      vector<string> vector_stuff = split_line(line, ' ');
      string word = vector_stuff[0];
      Col word_vec = Col::Zero(vector_stuff.size()-1);
      for (unsigned i = 0; i < word_vec.size(); ++i)
        word_vec(i, 0) = stof(vector_stuff[i+1]);
      vocab[word] = vocab_size++;
      word_vecs->push_back(word_vec);
    }
    cerr << "Read: " << vec_file_name << endl;
    cerr << "Vocab length: " << word_vecs->size() << endl;
    cerr << "Vector length: " << (*word_vecs)[0].size() << endl << endl;
    vec_file.close();

    assert (word_vecs->size() == vocab.size());
  } else {
    cerr << "Could not open " << vec_file;
    exit(0);
  }
}

void ReadVecsFromFile(const string& vec_file_name, mapUnsignedStr* t_vocab,
                      vector<Col>* word_vecs) {
  ifstream vec_file(vec_file_name.c_str());
  mapUnsignedStr& vocab = *t_vocab;
  unsigned vocab_size = 0;
  if (vec_file.is_open()) {
    string line;
    vocab.clear();
    while (getline(vec_file, line)) {
      vector<string> vector_stuff = split_line(line, ' ');
      string word = vector_stuff[0];
      Col word_vec = Col::Zero(vector_stuff.size()-1);
      for (unsigned i = 0; i < word_vec.size(); ++i)
        word_vec(i, 0) = stof(vector_stuff[i+1]);
      vocab[vocab_size++] = word;
      word_vecs->push_back(word_vec);
    }
    cerr << "Read: " << vec_file_name << endl;
    cerr << "Vocab length: " << word_vecs->size() << endl;
    cerr << "Vector length: " << (*word_vecs)[0].size() << endl << endl;
    vec_file.close();

    assert (word_vecs->size() == vocab.size());
  } else {
    cerr << "Could not open " << vec_file_name;
    exit(0);
  }
}

void ElemwiseTanh(Col* v) {
  for (unsigned i = 0; i < v->rows(); ++i)
    (*v)(i, 0) = tanh((*v)(i, 0));
}

/* v is the vector after taking tanh() */
void ElemwiseTanhGrad(const Col &v, Col* g) {
  for (int i = 0; i < v.rows(); ++i)
    (*g)(i, 0) = 1 - pow(v(i, 0), 2);
}

void ElemwiseAndrewNsnl(Col *v) {
  for (int i = 0; i < v->rows(); ++i) {
    double x = (*v)(i, 0);
    if (x) {
      bool flag = (x < 0);
      double y_n = flag ? -x : x;
      for (unsigned i = 0; i < 12; ++i) {
        const double sq = y_n * y_n;
        y_n = (2 * sq * y_n / 3 + x) / (sq + 1);
      }
      (*v)(i, 0) = flag ? -y_n : y_n;
    }
  }
}

void ElemwiseAndrewNsnlGrad(const Col &v, Col* g) {
  for (int i = 0; i < v.rows(); ++i)
    (*g)(i, 0) = 1 / (1 + pow(v(i, 0), 2));
}

double CosineSim(const Col& ci, const Col& cj) {
  return ci.dot(cj)/sqrt(ci.squaredNorm() * cj.squaredNorm());
}
<|endoftext|>


<commit_before>// Copyright (c) 2011-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "sync.h"
#include "util.h"

#include <stdio.h>
#include <set>

#ifdef DEBUG_LOCKCONTENTION
void PrintLockContention(const char* pszName, const char* pszFile, int nLine)
{
    LogPrintf("LOCKCONTENTION: %s\n", pszName);
    LogPrintf("Locker: %s:%d\n", pszFile, nLine);
}
#endif /* DEBUG_LOCKCONTENTION */

#ifdef DEBUG_LOCKORDER
//
// Early deadlock detection.
// Problem being solved:
//    Thread 1 locks  A, then B, then C
//    Thread 2 locks  D, then C, then A
//     --> may result in deadlock between the two threads, depending on when they run.
// Solution implemented here:
// Keep track of pairs of locks: (A before B), (A before C), etc.
// Complain if any thread tries to lock in a different order.
//

struct CLockLocation {
    CLockLocation(const char* pszName, const char* pszFile, int nLine, bool fTryIn)
    {
        mutexName = pszName;
        sourceFile = pszFile;
        sourceLine = nLine;
        fTry = fTryIn;
    }

    std::string ToString() const
    {
        return mutexName + "  " + sourceFile + ":" + ::ToString(sourceLine) + (fTry ? " (TRY)" : "");
    }

private:
    bool fTry;
    std::string mutexName;
    std::string sourceFile;
    int sourceLine;
};

typedef std::vector<std::pair<void*, CLockLocation> > LockStack;
typedef std::map<std::pair<void*, void*>, LockStack> LockOrders;
typedef std::set<std::pair<void*, void*> > InvLockOrders;

struct LockData {
    // Very ugly hack: as the global constructs and destructors run single
    // threaded, we use this boolean to know whether LockData still exists,
    // as DeleteLock can get called by global CCriticalSection destructors
    // after LockData disappears.
    bool available;
    LockData() : available(true) {}
    ~LockData() { available = false; }

    LockOrders lockorders;
    InvLockOrders invlockorders;
    std::mutex dd_mutex;
} static lockdata;

static thread_local std::unique_ptr<LockStack> lockstack;

static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch, const LockStack& s1, const LockStack& s2)
{
    LogPrintf("POTENTIAL DEADLOCK DETECTED\n");
    LogPrintf("Previous lock order was:\n");
    for (const std::pair<void*, CLockLocation> & i : s2) {
        if (i.first == mismatch.first) {
            LogPrintf(" (1)");
        }
        if (i.first == mismatch.second) {
            LogPrintf(" (2)");
        }
        LogPrintf(" %s\n", i.second.ToString());
    }
    LogPrintf("Current lock order is:\n");
    for (const std::pair<void*, CLockLocation> & i : s1) {
        if (i.first == mismatch.first) {
            LogPrintf(" (1)");
        }
        if (i.first == mismatch.second) {
            LogPrintf(" (2)");
        }
        LogPrintf(" %s\n", i.second.ToString());
    }
    assert(false);
}

static void push_lock(void* c, const CLockLocation& locklocation, bool fTry)
{
    if (!lockstack)
        lockstack.reset(new LockStack);

    std::lock_guard<std::mutex> lock(lockdata.dd_mutex);

    lockstack->push_back(std::make_pair(c, locklocation));

    for (const std::pair<void*, CLockLocation> & i : (*lockstack)) {
        if (i.first == c)
            break;

        std::pair<void*, void*> p1 = std::make_pair(i.first, c);
        if (lockdata.lockorders.count(p1))
            continue;
        lockdata.lockorders[p1] = (*lockstack);

        std::pair<void*, void*> p2 = std::make_pair(c, i.first);
        lockdata.invlockorders.insert(p2);
        if (lockdata.lockorders.count(p2))
            potential_deadlock_detected(p1, lockdata.lockorders[p2], lockdata.lockorders[p1]);
    }
}

static void pop_lock()
{
    (*lockstack).pop_back();
}

void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry)
{
    push_lock(cs, CLockLocation(pszName, pszFile, nLine, fTry), fTry);
}

void LeaveCritical()
{
    pop_lock();
}

std::string LocksHeld()
{
    std::string result;
    for (const std::pair<void*, CLockLocation> & i : *lockstack)
        result += i.second.ToString() + std::string("\n");
    return result;
}

void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs)
{
    for (const std::pair<void*, CLockLocation> & i : *lockstack)
        if (i.first == cs)
            return;
    fprintf(stderr, "Assertion failed: lock %s not held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld());
    abort();
}

void DeleteLock(void* cs)
{
    if (!lockdata.available) {
        // We're already shutting down.
        return;
    }
    std::lock_guard<std::mutex> lock(lockdata.dd_mutex);
    std::pair<void*, void*> item = std::make_pair(cs, (void*)0);
    LockOrders::iterator it = lockdata.lockorders.lower_bound(item);
    while (it != lockdata.lockorders.end() && it->first.first == cs) {
        std::pair<void*, void*> invitem = std::make_pair(it->first.second, it->first.first);
        lockdata.invlockorders.erase(invitem);
        lockdata.lockorders.erase(it++);
    }
    InvLockOrders::iterator invit = lockdata.invlockorders.lower_bound(item);
    while (invit != lockdata.invlockorders.end() && invit->first == cs) {
        std::pair<void*, void*> invinvitem = std::make_pair(invit->second, invit->first);
        lockdata.lockorders.erase(invinvitem);
        lockdata.invlockorders.erase(invit++);
    }
}

#endif /* DEBUG_LOCKORDER */
<commit_msg>Fix passing std::string to fprintf.<commit_after>// Copyright (c) 2011-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "sync.h"
#include "util.h"

#include <stdio.h>
#include <set>

#ifdef DEBUG_LOCKCONTENTION
void PrintLockContention(const char* pszName, const char* pszFile, int nLine)
{
    LogPrintf("LOCKCONTENTION: %s\n", pszName);
    LogPrintf("Locker: %s:%d\n", pszFile, nLine);
}
#endif /* DEBUG_LOCKCONTENTION */

#ifdef DEBUG_LOCKORDER
//
// Early deadlock detection.
// Problem being solved:
//    Thread 1 locks  A, then B, then C
//    Thread 2 locks  D, then C, then A
//     --> may result in deadlock between the two threads, depending on when they run.
// Solution implemented here:
// Keep track of pairs of locks: (A before B), (A before C), etc.
// Complain if any thread tries to lock in a different order.
//

struct CLockLocation {
    CLockLocation(const char* pszName, const char* pszFile, int nLine, bool fTryIn)
    {
        mutexName = pszName;
        sourceFile = pszFile;
        sourceLine = nLine;
        fTry = fTryIn;
    }

    std::string ToString() const
    {
        return mutexName + "  " + sourceFile + ":" + ::ToString(sourceLine) + (fTry ? " (TRY)" : "");
    }

private:
    bool fTry;
    std::string mutexName;
    std::string sourceFile;
    int sourceLine;
};

typedef std::vector<std::pair<void*, CLockLocation> > LockStack;
typedef std::map<std::pair<void*, void*>, LockStack> LockOrders;
typedef std::set<std::pair<void*, void*> > InvLockOrders;

struct LockData {
    // Very ugly hack: as the global constructs and destructors run single
    // threaded, we use this boolean to know whether LockData still exists,
    // as DeleteLock can get called by global CCriticalSection destructors
    // after LockData disappears.
    bool available;
    LockData() : available(true) {}
    ~LockData() { available = false; }

    LockOrders lockorders;
    InvLockOrders invlockorders;
    std::mutex dd_mutex;
} static lockdata;

static thread_local std::unique_ptr<LockStack> lockstack;

static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch, const LockStack& s1, const LockStack& s2)
{
    LogPrintf("POTENTIAL DEADLOCK DETECTED\n");
    LogPrintf("Previous lock order was:\n");
    for (const std::pair<void*, CLockLocation> & i : s2) {
        if (i.first == mismatch.first) {
            LogPrintf(" (1)");
        }
        if (i.first == mismatch.second) {
            LogPrintf(" (2)");
        }
        LogPrintf(" %s\n", i.second.ToString());
    }
    LogPrintf("Current lock order is:\n");
    for (const std::pair<void*, CLockLocation> & i : s1) {
        if (i.first == mismatch.first) {
            LogPrintf(" (1)");
        }
        if (i.first == mismatch.second) {
            LogPrintf(" (2)");
        }
        LogPrintf(" %s\n", i.second.ToString());
    }
    assert(false);
}

static void push_lock(void* c, const CLockLocation& locklocation, bool fTry)
{
    if (!lockstack)
        lockstack.reset(new LockStack);

    std::lock_guard<std::mutex> lock(lockdata.dd_mutex);

    lockstack->push_back(std::make_pair(c, locklocation));

    for (const std::pair<void*, CLockLocation> & i : (*lockstack)) {
        if (i.first == c)
            break;

        std::pair<void*, void*> p1 = std::make_pair(i.first, c);
        if (lockdata.lockorders.count(p1))
            continue;
        lockdata.lockorders[p1] = (*lockstack);

        std::pair<void*, void*> p2 = std::make_pair(c, i.first);
        lockdata.invlockorders.insert(p2);
        if (lockdata.lockorders.count(p2))
            potential_deadlock_detected(p1, lockdata.lockorders[p2], lockdata.lockorders[p1]);
    }
}

static void pop_lock()
{
    (*lockstack).pop_back();
}

void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry)
{
    push_lock(cs, CLockLocation(pszName, pszFile, nLine, fTry), fTry);
}

void LeaveCritical()
{
    pop_lock();
}

std::string LocksHeld()
{
    std::string result;
    for (const std::pair<void*, CLockLocation> & i : *lockstack)
        result += i.second.ToString() + std::string("\n");
    return result;
}

void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs)
{
    for (const std::pair<void*, CLockLocation> & i : *lockstack)
        if (i.first == cs)
            return;
    fprintf(stderr, "Assertion failed: lock %s not held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld().c_str());
    abort();
}

void DeleteLock(void* cs)
{
    if (!lockdata.available) {
        // We're already shutting down.
        return;
    }
    std::lock_guard<std::mutex> lock(lockdata.dd_mutex);
    std::pair<void*, void*> item = std::make_pair(cs, (void*)0);
    LockOrders::iterator it = lockdata.lockorders.lower_bound(item);
    while (it != lockdata.lockorders.end() && it->first.first == cs) {
        std::pair<void*, void*> invitem = std::make_pair(it->first.second, it->first.first);
        lockdata.invlockorders.erase(invitem);
        lockdata.lockorders.erase(it++);
    }
    InvLockOrders::iterator invit = lockdata.invlockorders.lower_bound(item);
    while (invit != lockdata.invlockorders.end() && invit->first == cs) {
        std::pair<void*, void*> invinvitem = std::make_pair(invit->second, invit->first);
        lockdata.lockorders.erase(invinvitem);
        lockdata.invlockorders.erase(invit++);
    }
}

#endif /* DEBUG_LOCKORDER */
<|endoftext|>


<commit_before>// Copyright (c) 2009 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 "chrome/browser/page_menu_model.h"

#include "base/logging.h"
#include "chrome/test/browser_with_test_window_test.h"
#include "chrome/test/menu_model_test.h"
#include "grit/generated_resources.h"
#include "testing/gtest/include/gtest/gtest.h"

class PageMenuModelTest : public BrowserWithTestWindowTest,
                          public MenuModelTest {
};

TEST_F(PageMenuModelTest, Basics) {
  PageMenuModel model(&delegate_, browser());
  int itemCount = model.GetItemCount();

  // Verify it has items. The number varies by platform, so we don't check
  // the exact number.
  EXPECT_GT(itemCount, 10);

  // Execute a couple of the items and make sure it gets back to our delegate.
  // We can't use CountEnabledExecutable() here because the encoding menu's
  // delegate is internal, it doesn't use the one we pass in.
  model.ActivatedAt(0);
  EXPECT_TRUE(model.IsEnabledAt(0));
  model.ActivatedAt(itemCount - 1);
  EXPECT_TRUE(model.IsEnabledAt(itemCount - 1));
  EXPECT_EQ(delegate_.execute_count_, 2);
  EXPECT_EQ(delegate_.enable_count_, 2);

  delegate_.execute_count_ = 0;
  delegate_.enable_count_ = 0;

  // Choose something from the zoom submenu and make sure it makes it back to
  // the delegate as well. Use the first submenu as the zoom one.
  int zoomModelIndex = -1;
  for (int i = 0; i < itemCount; ++i) {
    if (model.GetTypeAt(i) == menus::MenuModel::TYPE_SUBMENU) {
      zoomModelIndex = i;
      break;
    }
  }
  EXPECT_GT(zoomModelIndex, -1);
  menus::MenuModel* zoomModel = model.GetSubmenuModelAt(zoomModelIndex);
  EXPECT_TRUE(zoomModel);
  EXPECT_GT(zoomModel->GetItemCount(), 1);
  zoomModel->ActivatedAt(1);
  EXPECT_TRUE(zoomModel->IsEnabledAt(1));
  EXPECT_EQ(delegate_.execute_count_, 1);
  EXPECT_EQ(delegate_.enable_count_, 1);
}
<commit_msg>revert the revert<commit_after>// Copyright (c) 2009 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 "chrome/browser/page_menu_model.h"

#include "base/logging.h"
#include "chrome/test/browser_with_test_window_test.h"
#include "chrome/test/menu_model_test.h"
#include "grit/generated_resources.h"
#include "testing/gtest/include/gtest/gtest.h"

class PageMenuModelTest : public BrowserWithTestWindowTest,
                          public MenuModelTest {
};

TEST_F(PageMenuModelTest, Basics) {
  PageMenuModel model(&delegate_, browser());
  int itemCount = model.GetItemCount();

  // Verify it has items. The number varies by platform, so we don't check
  // the exact number.
  EXPECT_GT(itemCount, 10);

  // Execute a couple of the items and make sure it gets back to our delegate.
  // We can't use CountEnabledExecutable() here because the encoding menu's
  // delegate is internal, it doesn't use the one we pass in.
  model.ActivatedAt(0);
  EXPECT_TRUE(model.IsEnabledAt(0));
  model.ActivatedAt(3);
  EXPECT_TRUE(model.IsEnabledAt(3));
  EXPECT_EQ(delegate_.execute_count_, 2);
  EXPECT_EQ(delegate_.enable_count_, 2);

  delegate_.execute_count_ = 0;
  delegate_.enable_count_ = 0;

  // Choose something from the zoom submenu and make sure it makes it back to
  // the delegate as well. Use the first submenu as the zoom one.
  int zoomModelIndex = -1;
  for (int i = 0; i < itemCount; ++i) {
    if (model.GetTypeAt(i) == menus::MenuModel::TYPE_SUBMENU) {
      zoomModelIndex = i;
      break;
    }
  }
  EXPECT_GT(zoomModelIndex, -1);
  menus::MenuModel* zoomModel = model.GetSubmenuModelAt(zoomModelIndex);
  EXPECT_TRUE(zoomModel);
  EXPECT_GT(zoomModel->GetItemCount(), 1);
  zoomModel->ActivatedAt(1);
  EXPECT_TRUE(zoomModel->IsEnabledAt(1));
  EXPECT_EQ(delegate_.execute_count_, 1);
  EXPECT_EQ(delegate_.enable_count_, 1);
}
<|endoftext|>


<commit_before>// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/vespalib/eval/value_cache/constant_tensor_loader.h>
#include <vespa/vespalib/eval/simple_tensor_engine.h>
#include <vespa/vespalib/eval/tensor_spec.h>

using namespace vespalib::eval;

std::unique_ptr<Tensor> make_empty_tensor() {
    return SimpleTensorEngine::ref()
        .create(TensorSpec("tensor(x[2],y[2])"));
}

std::unique_ptr<Tensor> make_double_tensor() {
    return SimpleTensorEngine::ref()
        .create(TensorSpec("double"));
}

std::unique_ptr<Tensor> make_dense_tensor() {
    return SimpleTensorEngine::ref()
        .create(TensorSpec("tensor(x[2],y[2])")
                .add({{"x", 0}, {"y", 0}}, 1.0)
                .add({{"x", 0}, {"y", 1}}, 2.0)
                .add({{"x", 1}, {"y", 0}}, 3.0)
                .add({{"x", 1}, {"y", 1}}, 4.0));
}

std::unique_ptr<Tensor> make_sparse_tensor() {
    return SimpleTensorEngine::ref()
        .create(TensorSpec("tensor(x{},y{})")
                .add({{"x", "foo"}, {"y", "bar"}}, 1.0)
                .add({{"x", "bar"}, {"y", "foo"}}, 2.0));
}

std::unique_ptr<Tensor> make_mixed_tensor() {
    return SimpleTensorEngine::ref()
        .create(TensorSpec("tensor(x{},y[2])")
                .add({{"x", "foo"}, {"y", 0}}, 1.0)
                .add({{"x", "foo"}, {"y", 1}}, 2.0));
}

void verify_error(ConstantValue::UP actual) {
    EXPECT_TRUE(actual->type().is_error());
    EXPECT_TRUE(actual->value().is_error());
}

void verify_tensor(std::unique_ptr<Tensor> expect, ConstantValue::UP actual) {
    const auto &engine = expect->engine();
    ASSERT_EQUAL(engine.type_of(*expect), actual->type());
    EXPECT_TRUE(&engine == &actual->value().as_tensor()->engine());
    EXPECT_TRUE(engine.equal(*expect, *actual->value().as_tensor()));
}

TEST_F("require that invalid types loads an empty double", ConstantTensorLoader(SimpleTensorEngine::ref())) {
    TEST_DO(verify_tensor(make_double_tensor(), f1.create(TEST_PATH("dense.json"), "invalid type spec")));
}

TEST_F("require that invalid file name loads an empty tensor", ConstantTensorLoader(SimpleTensorEngine::ref())) {
    TEST_DO(verify_tensor(make_empty_tensor(), f1.create(TEST_PATH("missing_file.json"), "tensor(x[2],y[2])")));
}

TEST_F("require that invalid json loads an empty tensor", ConstantTensorLoader(SimpleTensorEngine::ref())) {
    TEST_DO(verify_tensor(make_empty_tensor(), f1.create(TEST_PATH("invalid.json"), "tensor(x[2],y[2])")));
}

TEST_F("require that dense tensors can be loaded", ConstantTensorLoader(SimpleTensorEngine::ref())) {
    TEST_DO(verify_tensor(make_dense_tensor(), f1.create(TEST_PATH("dense.json"), "tensor(x[2],y[2])")));
}

TEST_F("require that sparse tensors can be loaded", ConstantTensorLoader(SimpleTensorEngine::ref())) {
    TEST_DO(verify_tensor(make_sparse_tensor(), f1.create(TEST_PATH("sparse.json"), "tensor(x{},y{})")));
}

TEST_F("require that mixed tensors can be loaded", ConstantTensorLoader(SimpleTensorEngine::ref())) {
    TEST_DO(verify_tensor(make_mixed_tensor(), f1.create(TEST_PATH("mixed.json"), "tensor(x{},y[2])")));
}

TEST_MAIN() { TEST_RUN_ALL(); }
<commit_msg>garbage collect unused verify_error<commit_after>// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/vespalib/eval/value_cache/constant_tensor_loader.h>
#include <vespa/vespalib/eval/simple_tensor_engine.h>
#include <vespa/vespalib/eval/tensor_spec.h>

using namespace vespalib::eval;

std::unique_ptr<Tensor> make_empty_tensor() {
    return SimpleTensorEngine::ref()
        .create(TensorSpec("tensor(x[2],y[2])"));
}

std::unique_ptr<Tensor> make_double_tensor() {
    return SimpleTensorEngine::ref()
        .create(TensorSpec("double"));
}

std::unique_ptr<Tensor> make_dense_tensor() {
    return SimpleTensorEngine::ref()
        .create(TensorSpec("tensor(x[2],y[2])")
                .add({{"x", 0}, {"y", 0}}, 1.0)
                .add({{"x", 0}, {"y", 1}}, 2.0)
                .add({{"x", 1}, {"y", 0}}, 3.0)
                .add({{"x", 1}, {"y", 1}}, 4.0));
}

std::unique_ptr<Tensor> make_sparse_tensor() {
    return SimpleTensorEngine::ref()
        .create(TensorSpec("tensor(x{},y{})")
                .add({{"x", "foo"}, {"y", "bar"}}, 1.0)
                .add({{"x", "bar"}, {"y", "foo"}}, 2.0));
}

std::unique_ptr<Tensor> make_mixed_tensor() {
    return SimpleTensorEngine::ref()
        .create(TensorSpec("tensor(x{},y[2])")
                .add({{"x", "foo"}, {"y", 0}}, 1.0)
                .add({{"x", "foo"}, {"y", 1}}, 2.0));
}

void verify_tensor(std::unique_ptr<Tensor> expect, ConstantValue::UP actual) {
    const auto &engine = expect->engine();
    ASSERT_EQUAL(engine.type_of(*expect), actual->type());
    EXPECT_TRUE(&engine == &actual->value().as_tensor()->engine());
    EXPECT_TRUE(engine.equal(*expect, *actual->value().as_tensor()));
}

TEST_F("require that invalid types loads an empty double", ConstantTensorLoader(SimpleTensorEngine::ref())) {
    TEST_DO(verify_tensor(make_double_tensor(), f1.create(TEST_PATH("dense.json"), "invalid type spec")));
}

TEST_F("require that invalid file name loads an empty tensor", ConstantTensorLoader(SimpleTensorEngine::ref())) {
    TEST_DO(verify_tensor(make_empty_tensor(), f1.create(TEST_PATH("missing_file.json"), "tensor(x[2],y[2])")));
}

TEST_F("require that invalid json loads an empty tensor", ConstantTensorLoader(SimpleTensorEngine::ref())) {
    TEST_DO(verify_tensor(make_empty_tensor(), f1.create(TEST_PATH("invalid.json"), "tensor(x[2],y[2])")));
}

TEST_F("require that dense tensors can be loaded", ConstantTensorLoader(SimpleTensorEngine::ref())) {
    TEST_DO(verify_tensor(make_dense_tensor(), f1.create(TEST_PATH("dense.json"), "tensor(x[2],y[2])")));
}

TEST_F("require that sparse tensors can be loaded", ConstantTensorLoader(SimpleTensorEngine::ref())) {
    TEST_DO(verify_tensor(make_sparse_tensor(), f1.create(TEST_PATH("sparse.json"), "tensor(x{},y{})")));
}

TEST_F("require that mixed tensors can be loaded", ConstantTensorLoader(SimpleTensorEngine::ref())) {
    TEST_DO(verify_tensor(make_mixed_tensor(), f1.create(TEST_PATH("mixed.json"), "tensor(x{},y[2])")));
}

TEST_MAIN() { TEST_RUN_ALL(); }
<|endoftext|>


<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 "chrome/browser/shell_dialogs.h"

#include "app/l10n_util.h"
#include "base/callback.h"
#include "base/file_path.h"
#include "base/json/json_reader.h"
#include "base/scoped_ptr.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/dom_ui/html_dialog_ui.h"
#include "chrome/browser/shell_dialogs.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/views/html_dialog_view.h"
#include "chrome/common/url_constants.h"
#include "grit/generated_resources.h"
#include "views/window/non_client_view.h"
#include "views/window/window.h"

namespace {

static const wchar_t* kKeyNamePath = L"path";

};  // namespace

// Implementation of SelectFileDialog that shows an UI for choosing a file
// or folder using FileBrowseUI.
class SelectFileDialogImpl : public SelectFileDialog {
 public:
  explicit SelectFileDialogImpl(Listener* listener);

  // BaseShellDialog implementation.
  virtual bool IsRunning(gfx::NativeWindow parent_window) const;
  virtual void ListenerDestroyed();

  // SelectFileDialog implementation.
  // |params| is user data we pass back via the Listener interface.
  virtual void SelectFile(Type type,
                          const string16& title,
                          const FilePath& default_path,
                          const FileTypeInfo* file_types,
                          int file_type_index,
                          const FilePath::StringType& default_extension,
                          gfx::NativeWindow owning_window,
                          void* params);

 private:
  virtual ~SelectFileDialogImpl();

  class FileBrowseDelegate : public HtmlDialogUIDelegate {
   public:
    FileBrowseDelegate(SelectFileDialogImpl* owner,
                       Type type,
                       const std::wstring& title,
                       const FilePath& default_path,
                       const FileTypeInfo* file_types,
                       int file_type_index,
                       const FilePath::StringType& default_extension,
                       gfx::NativeWindow parent,
                       void* params);

    // Owner of this FileBrowseDelegate.
    scoped_refptr<SelectFileDialogImpl> owner_;

    // Parent window.
    gfx::NativeWindow parent_;

    // The type of dialog we are showing the user.
    Type type_;

    // The dialog title.
    std::wstring title_;

    // Default path of the file dialog.
    FilePath default_path_;

    // The file filters.
    FileTypeInfo file_types_;

    // The index of the default selected file filter.
    // Note: This starts from 1, not 0.
    int file_type_index_;

    // Default extension to be added to file if user does not type one.
    FilePath::StringType default_extension_;

    // Associated user data.
    void* params_;

   private:
    ~FileBrowseDelegate();

    // Overridden from HtmlDialogUI::Delegate:
    virtual bool IsDialogModal() const;
    virtual std::wstring GetDialogTitle() const;
    virtual GURL GetDialogContentURL() const;
    virtual void GetDOMMessageHandlers(
        std::vector<DOMMessageHandler*>* handlers) const;
    virtual void GetDialogSize(gfx::Size* size) const;
    virtual std::string GetDialogArgs() const;
    virtual void OnDialogClosed(const std::string& json_retval);

    DISALLOW_COPY_AND_ASSIGN(FileBrowseDelegate);
  };

  class FileBrowseDelegateHandler : public DOMMessageHandler {
   public:
    explicit FileBrowseDelegateHandler(FileBrowseDelegate* delegate);

    // DOMMessageHandler implementation.
    virtual void RegisterMessages();

    // Callback for the "setDialogTitle" message.
    void HandleSetDialogTitle(const Value* value);

   private:
    FileBrowseDelegate* delegate_;

    DISALLOW_COPY_AND_ASSIGN(FileBrowseDelegateHandler);
  };

  // Notification from FileBrowseDelegate when file browse UI is dismissed.
  void OnDialogClosed(FileBrowseDelegate* delegate, const std::string& json);

  // The set of all parent windows for which we are currently running dialogs.
  std::set<gfx::NativeWindow> parents_;

  // The set of all FileBrowseDelegate that we are currently running.
  std::set<FileBrowseDelegate*> delegates_;

  // The listener to be notified of selection completion.
  Listener* listener_;

  DISALLOW_COPY_AND_ASSIGN(SelectFileDialogImpl);
};

// static
SelectFileDialog* SelectFileDialog::Create(Listener* listener) {
  DCHECK(!ChromeThread::CurrentlyOn(ChromeThread::IO));
  DCHECK(!ChromeThread::CurrentlyOn(ChromeThread::FILE));
  return new SelectFileDialogImpl(listener);
}

SelectFileDialogImpl::SelectFileDialogImpl(Listener* listener)
    : listener_(listener) {
}

SelectFileDialogImpl::~SelectFileDialogImpl() {
  // All dialogs should be dismissed by now.
  DCHECK(parents_.empty() && delegates_.empty());
}

bool SelectFileDialogImpl::IsRunning(gfx::NativeWindow parent_window) const {
  return parent_window && parents_.find(parent_window) != parents_.end();
}

void SelectFileDialogImpl::ListenerDestroyed() {
  listener_ = NULL;
}

void SelectFileDialogImpl::SelectFile(
    Type type,
    const string16& title,
    const FilePath& default_path,
    const FileTypeInfo* file_types,
    int file_type_index,
    const FilePath::StringType& default_extension,
    gfx::NativeWindow owning_window,
    void* params) {
  std::wstring title_string;
  if (title.empty()) {
    int string_id;
    switch (type) {
      case SELECT_FOLDER:
        string_id = IDS_SELECT_FOLDER_DIALOG_TITLE;
        break;
      case SELECT_OPEN_FILE:
      case SELECT_OPEN_MULTI_FILE:
        string_id = IDS_OPEN_FILE_DIALOG_TITLE;
        break;
      case SELECT_SAVEAS_FILE:
        string_id = IDS_SAVE_AS_DIALOG_TITLE;
        break;
      default:
        NOTREACHED();
        return;
    }
    title_string = l10n_util::GetString(string_id);
  } else {
    title_string = UTF16ToWide(title);
  }

  if (owning_window)
    parents_.insert(owning_window);

  FileBrowseDelegate* file_browse_delegate = new FileBrowseDelegate(this,
      type, title_string, default_path, file_types, file_type_index,
      default_extension, owning_window, params);
  delegates_.insert(file_browse_delegate);

  Browser* browser = BrowserList::GetLastActive();
  DCHECK(browser);
  browser->BrowserShowHtmlDialog(file_browse_delegate, owning_window);
}

void SelectFileDialogImpl::OnDialogClosed(FileBrowseDelegate* delegate,
                                          const std::string& json) {
  // Nothing to do if listener_ is gone.

  if (!listener_)
    return;

  bool notification_fired = false;

  if (!json.empty()) {
    scoped_ptr<Value> value(base::JSONReader::Read(json, false));
    if (!value.get() || !value->IsType(Value::TYPE_DICTIONARY)) {
      // Bad json value returned.
      NOTREACHED();
    } else {
      const DictionaryValue* dict = static_cast<DictionaryValue*>(value.get());
      if (delegate->type_ == SELECT_OPEN_FILE ||
          delegate->type_ == SELECT_SAVEAS_FILE ||
          delegate->type_ == SELECT_FOLDER) {
        std::wstring path_string;
        if (dict->HasKey(kKeyNamePath) &&
            dict->GetString(kKeyNamePath, &path_string)) {
          FilePath path = FilePath::FromWStringHack(path_string);

          listener_->FileSelected(path, 0, delegate->params_);
          notification_fired = true;
        }
      } else if (delegate->type_ == SELECT_OPEN_MULTI_FILE) {
        ListValue* paths_value = NULL;
        if (dict->HasKey(kKeyNamePath) &&
            dict->GetList(kKeyNamePath, &paths_value) &&
            paths_value) {
          std::vector<FilePath> paths;
          paths.reserve(paths_value->GetSize());
          for (size_t i = 0; i < paths_value->GetSize(); ++i) {
            std::wstring path_string;
            if (paths_value->GetString(i, &path_string) &&
                !path_string.empty()) {
              paths.push_back(FilePath::FromWStringHack(path_string));
            }
          }

          listener_->MultiFilesSelected(paths, delegate->params_);
          notification_fired = true;
        }
      } else {
        NOTREACHED();
      }
    }
  }

  // Always notify listener when dialog is dismissed.
  if (!notification_fired)
    listener_->FileSelectionCanceled(delegate->params_);

  parents_.erase(delegate->parent_);
  delegates_.erase(delegate);
}

SelectFileDialogImpl::FileBrowseDelegate::FileBrowseDelegate(
    SelectFileDialogImpl* owner,
    Type type,
    const std::wstring& title,
    const FilePath& default_path,
    const FileTypeInfo* file_types,
    int file_type_index,
    const FilePath::StringType& default_extension,
    gfx::NativeWindow parent,
    void* params)
  : owner_(owner),
    parent_(parent),
    type_(type),
    title_(title),
    default_path_(default_path),
    file_type_index_(file_type_index),
    default_extension_(default_extension),
    params_(params) {
  if (file_types)
    file_types_ = *file_types;
  else
    file_types_.include_all_files = true;
}

SelectFileDialogImpl::FileBrowseDelegate::~FileBrowseDelegate() {
}

bool SelectFileDialogImpl::FileBrowseDelegate::IsDialogModal() const {
  return true;
}

std::wstring SelectFileDialogImpl::FileBrowseDelegate::GetDialogTitle() const {
  return title_;
}

GURL SelectFileDialogImpl::FileBrowseDelegate::GetDialogContentURL() const {
  std::string url_string(chrome::kChromeUIFileBrowseURL);

  return GURL(url_string);
}

void SelectFileDialogImpl::FileBrowseDelegate::GetDOMMessageHandlers(
    std::vector<DOMMessageHandler*>* handlers) const {
  handlers->push_back(new FileBrowseDelegateHandler(
      const_cast<FileBrowseDelegate*>(this)));
  return;
}

void SelectFileDialogImpl::FileBrowseDelegate::GetDialogSize(
    gfx::Size* size) const {
  size->SetSize(320, 240);
}

std::string SelectFileDialogImpl::FileBrowseDelegate::GetDialogArgs() const {
  // SelectFile inputs as json.
  //  {
  //    "type"            : "open",   // (or "open_multiple", "save", "folder"
  //    "all_files"       : true,
  //    "file_types"      : {
  //                          "exts" : [ ["htm", "html"], ["txt"] ],
  //                          "desc" : [ "HTML files", "Text files" ],
  //                        },
  //    "file_type_index" : 1,    // 1-based file type index.
  //  }
  //  See browser/shell_dialogs.h for more details.

  std::string type_string;
  switch (type_) {
    case SELECT_FOLDER:
      type_string = "folder";
      break;
    case SELECT_OPEN_FILE:
      type_string = "open";
      break;
    case SELECT_OPEN_MULTI_FILE:
      type_string = "open_multiple";
      break;
    case SELECT_SAVEAS_FILE:
      type_string = "save";
      break;
    default:
      NOTREACHED();
      return std::string();
  }

  std::string exts_list;
  std::string desc_list;
  for (size_t i = 0; i < file_types_.extensions.size(); ++i) {
    DCHECK(!file_types_.extensions[i].empty());

    std::string exts;
    for (size_t j = 0; j < file_types_.extensions[i].size(); ++j) {
      if (!exts.empty())
        exts.append(",");
      StringAppendF(&exts, "\"%s\"", file_types_.extensions[i][j].c_str());
    }

    if (!exts_list.empty())
      exts_list.append(",");
    StringAppendF(&exts_list, "[%s]", exts.c_str());

    std::string desc;
    if (i < file_types_.extension_description_overrides.size()) {
      desc = UTF16ToUTF8(file_types_.extension_description_overrides[i]);
    } else {
#if defined(OS_WIN)
      desc = WideToUTF8(file_types_.extensions[i][0]);
#elif defined(OS_POSIX)
      desc = file_types_.extensions[i][0];
#else
      NOTIMPLEMENTED();
#endif
    }

    if (!desc_list.empty())
      desc_list.append(",");
    StringAppendF(&desc_list, "\"%s\"", desc.c_str());
  }

  std::string filename = default_path_.BaseName().value();

  return StringPrintf("{"
        "\"type\":\"%s\","
        "\"all_files\":%s,"
        "\"current_file\":\"%s\","
        "\"file_types\":{\"exts\":[%s],\"desc\":[%s]},"
        "\"file_type_index\":%d"
      "}",
      type_string.c_str(),
      file_types_.include_all_files ? "true" : "false",
      filename.c_str(),
      exts_list.c_str(),
      desc_list.c_str(),
      file_type_index_);
}

void SelectFileDialogImpl::FileBrowseDelegate::OnDialogClosed(
    const std::string& json_retval) {
  owner_->OnDialogClosed(this, json_retval);
  delete this;
  return;
}

SelectFileDialogImpl::FileBrowseDelegateHandler::FileBrowseDelegateHandler(
    FileBrowseDelegate* delegate)
    : delegate_(delegate) {
}

void SelectFileDialogImpl::FileBrowseDelegateHandler::RegisterMessages() {
  dom_ui_->RegisterMessageCallback("setDialogTitle",
      NewCallback(this, &FileBrowseDelegateHandler::HandleSetDialogTitle));
}

void SelectFileDialogImpl::FileBrowseDelegateHandler::HandleSetDialogTitle(
    const Value* value) {
  std::wstring new_title = ExtractStringValue(value);
  if (new_title != delegate_->title_) {
    delegate_->title_ = new_title;

    // Notify the containing view about the title change.
    // The current HtmlDialogUIDelegate and HtmlDialogView does not support
    // dynamic title change. We hijacked the mechanism between HTMLDialogUI
    // and HtmlDialogView to get the HtmlDialgoView and forced it to update
    // its title.
    // TODO(xiyuan): Change this when the infrastructure is improved.
    HtmlDialogUIDelegate** delegate = HtmlDialogUI::GetPropertyAccessor().
        GetProperty(dom_ui_->tab_contents()->property_bag());
    HtmlDialogView* containing_view = static_cast<HtmlDialogView*>(*delegate);
    DCHECK(containing_view);

    containing_view->GetWindow()->UpdateWindowTitle();
    containing_view->GetWindow()->GetNonClientView()->SchedulePaint();
  }
}
<commit_msg>Fix for assert in SavePackage::ContinueSave(): save package type index outside of allowed bounds. <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 "chrome/browser/shell_dialogs.h"

#include "app/l10n_util.h"
#include "base/callback.h"
#include "base/file_path.h"
#include "base/json/json_reader.h"
#include "base/scoped_ptr.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/dom_ui/html_dialog_ui.h"
#include "chrome/browser/shell_dialogs.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/views/html_dialog_view.h"
#include "chrome/common/url_constants.h"
#include "grit/generated_resources.h"
#include "views/window/non_client_view.h"
#include "views/window/window.h"

namespace {

static const wchar_t* kKeyNamePath = L"path";
static const int kSaveCompletePageIndex = 2;

};  // namespace

// Implementation of SelectFileDialog that shows an UI for choosing a file
// or folder using FileBrowseUI.
class SelectFileDialogImpl : public SelectFileDialog {
 public:
  explicit SelectFileDialogImpl(Listener* listener);

  // BaseShellDialog implementation.
  virtual bool IsRunning(gfx::NativeWindow parent_window) const;
  virtual void ListenerDestroyed();

  // SelectFileDialog implementation.
  // |params| is user data we pass back via the Listener interface.
  virtual void SelectFile(Type type,
                          const string16& title,
                          const FilePath& default_path,
                          const FileTypeInfo* file_types,
                          int file_type_index,
                          const FilePath::StringType& default_extension,
                          gfx::NativeWindow owning_window,
                          void* params);

 private:
  virtual ~SelectFileDialogImpl();

  class FileBrowseDelegate : public HtmlDialogUIDelegate {
   public:
    FileBrowseDelegate(SelectFileDialogImpl* owner,
                       Type type,
                       const std::wstring& title,
                       const FilePath& default_path,
                       const FileTypeInfo* file_types,
                       int file_type_index,
                       const FilePath::StringType& default_extension,
                       gfx::NativeWindow parent,
                       void* params);

    // Owner of this FileBrowseDelegate.
    scoped_refptr<SelectFileDialogImpl> owner_;

    // Parent window.
    gfx::NativeWindow parent_;

    // The type of dialog we are showing the user.
    Type type_;

    // The dialog title.
    std::wstring title_;

    // Default path of the file dialog.
    FilePath default_path_;

    // The file filters.
    FileTypeInfo file_types_;

    // The index of the default selected file filter.
    // Note: This starts from 1, not 0.
    int file_type_index_;

    // Default extension to be added to file if user does not type one.
    FilePath::StringType default_extension_;

    // Associated user data.
    void* params_;

   private:
    ~FileBrowseDelegate();

    // Overridden from HtmlDialogUI::Delegate:
    virtual bool IsDialogModal() const;
    virtual std::wstring GetDialogTitle() const;
    virtual GURL GetDialogContentURL() const;
    virtual void GetDOMMessageHandlers(
        std::vector<DOMMessageHandler*>* handlers) const;
    virtual void GetDialogSize(gfx::Size* size) const;
    virtual std::string GetDialogArgs() const;
    virtual void OnDialogClosed(const std::string& json_retval);

    DISALLOW_COPY_AND_ASSIGN(FileBrowseDelegate);
  };

  class FileBrowseDelegateHandler : public DOMMessageHandler {
   public:
    explicit FileBrowseDelegateHandler(FileBrowseDelegate* delegate);

    // DOMMessageHandler implementation.
    virtual void RegisterMessages();

    // Callback for the "setDialogTitle" message.
    void HandleSetDialogTitle(const Value* value);

   private:
    FileBrowseDelegate* delegate_;

    DISALLOW_COPY_AND_ASSIGN(FileBrowseDelegateHandler);
  };

  // Notification from FileBrowseDelegate when file browse UI is dismissed.
  void OnDialogClosed(FileBrowseDelegate* delegate, const std::string& json);

  // The set of all parent windows for which we are currently running dialogs.
  std::set<gfx::NativeWindow> parents_;

  // The set of all FileBrowseDelegate that we are currently running.
  std::set<FileBrowseDelegate*> delegates_;

  // The listener to be notified of selection completion.
  Listener* listener_;

  DISALLOW_COPY_AND_ASSIGN(SelectFileDialogImpl);
};

// static
SelectFileDialog* SelectFileDialog::Create(Listener* listener) {
  DCHECK(!ChromeThread::CurrentlyOn(ChromeThread::IO));
  DCHECK(!ChromeThread::CurrentlyOn(ChromeThread::FILE));
  return new SelectFileDialogImpl(listener);
}

SelectFileDialogImpl::SelectFileDialogImpl(Listener* listener)
    : listener_(listener) {
}

SelectFileDialogImpl::~SelectFileDialogImpl() {
  // All dialogs should be dismissed by now.
  DCHECK(parents_.empty() && delegates_.empty());
}

bool SelectFileDialogImpl::IsRunning(gfx::NativeWindow parent_window) const {
  return parent_window && parents_.find(parent_window) != parents_.end();
}

void SelectFileDialogImpl::ListenerDestroyed() {
  listener_ = NULL;
}

void SelectFileDialogImpl::SelectFile(
    Type type,
    const string16& title,
    const FilePath& default_path,
    const FileTypeInfo* file_types,
    int file_type_index,
    const FilePath::StringType& default_extension,
    gfx::NativeWindow owning_window,
    void* params) {
  std::wstring title_string;
  if (title.empty()) {
    int string_id;
    switch (type) {
      case SELECT_FOLDER:
        string_id = IDS_SELECT_FOLDER_DIALOG_TITLE;
        break;
      case SELECT_OPEN_FILE:
      case SELECT_OPEN_MULTI_FILE:
        string_id = IDS_OPEN_FILE_DIALOG_TITLE;
        break;
      case SELECT_SAVEAS_FILE:
        string_id = IDS_SAVE_AS_DIALOG_TITLE;
        break;
      default:
        NOTREACHED();
        return;
    }
    title_string = l10n_util::GetString(string_id);
  } else {
    title_string = UTF16ToWide(title);
  }

  if (owning_window)
    parents_.insert(owning_window);

  FileBrowseDelegate* file_browse_delegate = new FileBrowseDelegate(this,
      type, title_string, default_path, file_types, file_type_index,
      default_extension, owning_window, params);
  delegates_.insert(file_browse_delegate);

  Browser* browser = BrowserList::GetLastActive();
  DCHECK(browser);
  browser->BrowserShowHtmlDialog(file_browse_delegate, owning_window);
}

void SelectFileDialogImpl::OnDialogClosed(FileBrowseDelegate* delegate,
                                          const std::string& json) {
  // Nothing to do if listener_ is gone.

  if (!listener_)
    return;

  bool notification_fired = false;

  if (!json.empty()) {
    scoped_ptr<Value> value(base::JSONReader::Read(json, false));
    if (!value.get() || !value->IsType(Value::TYPE_DICTIONARY)) {
      // Bad json value returned.
      NOTREACHED();
    } else {
      const DictionaryValue* dict = static_cast<DictionaryValue*>(value.get());
      if (delegate->type_ == SELECT_OPEN_FILE ||
          delegate->type_ == SELECT_SAVEAS_FILE ||
          delegate->type_ == SELECT_FOLDER) {
        std::wstring path_string;
        if (dict->HasKey(kKeyNamePath) &&
            dict->GetString(kKeyNamePath, &path_string)) {
          FilePath path = FilePath::FromWStringHack(path_string);

          listener_->FileSelected(path, kSaveCompletePageIndex,
                                  delegate->params_);
          notification_fired = true;
        }
      } else if (delegate->type_ == SELECT_OPEN_MULTI_FILE) {
        ListValue* paths_value = NULL;
        if (dict->HasKey(kKeyNamePath) &&
            dict->GetList(kKeyNamePath, &paths_value) &&
            paths_value) {
          std::vector<FilePath> paths;
          paths.reserve(paths_value->GetSize());
          for (size_t i = 0; i < paths_value->GetSize(); ++i) {
            std::wstring path_string;
            if (paths_value->GetString(i, &path_string) &&
                !path_string.empty()) {
              paths.push_back(FilePath::FromWStringHack(path_string));
            }
          }

          listener_->MultiFilesSelected(paths, delegate->params_);
          notification_fired = true;
        }
      } else {
        NOTREACHED();
      }
    }
  }

  // Always notify listener when dialog is dismissed.
  if (!notification_fired)
    listener_->FileSelectionCanceled(delegate->params_);

  parents_.erase(delegate->parent_);
  delegates_.erase(delegate);
}

SelectFileDialogImpl::FileBrowseDelegate::FileBrowseDelegate(
    SelectFileDialogImpl* owner,
    Type type,
    const std::wstring& title,
    const FilePath& default_path,
    const FileTypeInfo* file_types,
    int file_type_index,
    const FilePath::StringType& default_extension,
    gfx::NativeWindow parent,
    void* params)
  : owner_(owner),
    parent_(parent),
    type_(type),
    title_(title),
    default_path_(default_path),
    file_type_index_(file_type_index),
    default_extension_(default_extension),
    params_(params) {
  if (file_types)
    file_types_ = *file_types;
  else
    file_types_.include_all_files = true;
}

SelectFileDialogImpl::FileBrowseDelegate::~FileBrowseDelegate() {
}

bool SelectFileDialogImpl::FileBrowseDelegate::IsDialogModal() const {
  return true;
}

std::wstring SelectFileDialogImpl::FileBrowseDelegate::GetDialogTitle() const {
  return title_;
}

GURL SelectFileDialogImpl::FileBrowseDelegate::GetDialogContentURL() const {
  std::string url_string(chrome::kChromeUIFileBrowseURL);

  return GURL(url_string);
}

void SelectFileDialogImpl::FileBrowseDelegate::GetDOMMessageHandlers(
    std::vector<DOMMessageHandler*>* handlers) const {
  handlers->push_back(new FileBrowseDelegateHandler(
      const_cast<FileBrowseDelegate*>(this)));
  return;
}

void SelectFileDialogImpl::FileBrowseDelegate::GetDialogSize(
    gfx::Size* size) const {
  size->SetSize(320, 240);
}

std::string SelectFileDialogImpl::FileBrowseDelegate::GetDialogArgs() const {
  // SelectFile inputs as json.
  //  {
  //    "type"            : "open",   // (or "open_multiple", "save", "folder"
  //    "all_files"       : true,
  //    "file_types"      : {
  //                          "exts" : [ ["htm", "html"], ["txt"] ],
  //                          "desc" : [ "HTML files", "Text files" ],
  //                        },
  //    "file_type_index" : 1,    // 1-based file type index.
  //  }
  //  See browser/shell_dialogs.h for more details.

  std::string type_string;
  switch (type_) {
    case SELECT_FOLDER:
      type_string = "folder";
      break;
    case SELECT_OPEN_FILE:
      type_string = "open";
      break;
    case SELECT_OPEN_MULTI_FILE:
      type_string = "open_multiple";
      break;
    case SELECT_SAVEAS_FILE:
      type_string = "save";
      break;
    default:
      NOTREACHED();
      return std::string();
  }

  std::string exts_list;
  std::string desc_list;
  for (size_t i = 0; i < file_types_.extensions.size(); ++i) {
    DCHECK(!file_types_.extensions[i].empty());

    std::string exts;
    for (size_t j = 0; j < file_types_.extensions[i].size(); ++j) {
      if (!exts.empty())
        exts.append(",");
      StringAppendF(&exts, "\"%s\"", file_types_.extensions[i][j].c_str());
    }

    if (!exts_list.empty())
      exts_list.append(",");
    StringAppendF(&exts_list, "[%s]", exts.c_str());

    std::string desc;
    if (i < file_types_.extension_description_overrides.size()) {
      desc = UTF16ToUTF8(file_types_.extension_description_overrides[i]);
    } else {
#if defined(OS_WIN)
      desc = WideToUTF8(file_types_.extensions[i][0]);
#elif defined(OS_POSIX)
      desc = file_types_.extensions[i][0];
#else
      NOTIMPLEMENTED();
#endif
    }

    if (!desc_list.empty())
      desc_list.append(",");
    StringAppendF(&desc_list, "\"%s\"", desc.c_str());
  }

  std::string filename = default_path_.BaseName().value();

  return StringPrintf("{"
        "\"type\":\"%s\","
        "\"all_files\":%s,"
        "\"current_file\":\"%s\","
        "\"file_types\":{\"exts\":[%s],\"desc\":[%s]},"
        "\"file_type_index\":%d"
      "}",
      type_string.c_str(),
      file_types_.include_all_files ? "true" : "false",
      filename.c_str(),
      exts_list.c_str(),
      desc_list.c_str(),
      file_type_index_);
}

void SelectFileDialogImpl::FileBrowseDelegate::OnDialogClosed(
    const std::string& json_retval) {
  owner_->OnDialogClosed(this, json_retval);
  delete this;
  return;
}

SelectFileDialogImpl::FileBrowseDelegateHandler::FileBrowseDelegateHandler(
    FileBrowseDelegate* delegate)
    : delegate_(delegate) {
}

void SelectFileDialogImpl::FileBrowseDelegateHandler::RegisterMessages() {
  dom_ui_->RegisterMessageCallback("setDialogTitle",
      NewCallback(this, &FileBrowseDelegateHandler::HandleSetDialogTitle));
}

void SelectFileDialogImpl::FileBrowseDelegateHandler::HandleSetDialogTitle(
    const Value* value) {
  std::wstring new_title = ExtractStringValue(value);
  if (new_title != delegate_->title_) {
    delegate_->title_ = new_title;

    // Notify the containing view about the title change.
    // The current HtmlDialogUIDelegate and HtmlDialogView does not support
    // dynamic title change. We hijacked the mechanism between HTMLDialogUI
    // and HtmlDialogView to get the HtmlDialgoView and forced it to update
    // its title.
    // TODO(xiyuan): Change this when the infrastructure is improved.
    HtmlDialogUIDelegate** delegate = HtmlDialogUI::GetPropertyAccessor().
        GetProperty(dom_ui_->tab_contents()->property_bag());
    HtmlDialogView* containing_view = static_cast<HtmlDialogView*>(*delegate);
    DCHECK(containing_view);

    containing_view->GetWindow()->UpdateWindowTitle();
    containing_view->GetWindow()->GetNonClientView()->SchedulePaint();
  }
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <memory>

#include "webrtc/modules/desktop_capture/mouse_cursor_monitor.h"

#include <X11/extensions/Xfixes.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>

#include "webrtc/base/logging.h"
#include "webrtc/modules/desktop_capture/desktop_capture_options.h"
#include "webrtc/modules/desktop_capture/desktop_frame.h"
#include "webrtc/modules/desktop_capture/mouse_cursor.h"
#include "webrtc/modules/desktop_capture/x11/x_error_trap.h"

namespace {

// WindowCapturer returns window IDs of X11 windows with WM_STATE attribute.
// These windows may not be immediate children of the root window, because
// window managers may re-parent them to add decorations. However,
// XQueryPointer() expects to be passed children of the root. This function
// searches up the list of the windows to find the root child that corresponds
// to |window|.
Window GetTopLevelWindow(Display* display, Window window) {
  while (true) {
    // If the window is in WithdrawnState then look at all of its children.
    ::Window root, parent;
    ::Window *children;
    unsigned int num_children;
    if (!XQueryTree(display, window, &root, &parent, &children,
                    &num_children)) {
      LOG(LS_ERROR) << "Failed to query for child windows although window"
                    << "does not have a valid WM_STATE.";
      return None;
    }
    if (children)
      XFree(children);

    if (parent == root)
      break;

    window = parent;
  }

  return window;
}

}  // namespace

namespace webrtc {

class MouseCursorMonitorX11 : public MouseCursorMonitor,
                              public SharedXDisplay::XEventHandler {
 public:
  MouseCursorMonitorX11(const DesktopCaptureOptions& options, Window window);
  ~MouseCursorMonitorX11() override;

  void Init(Callback* callback, Mode mode) override;
  void Capture() override;

 private:
  // SharedXDisplay::XEventHandler interface.
  bool HandleXEvent(const XEvent& event) override;

  Display* display() { return x_display_->display(); }

  // Captures current cursor shape and stores it in |cursor_shape_|.
  void CaptureCursor();

  rtc::scoped_refptr<SharedXDisplay> x_display_;
  Callback* callback_;
  Mode mode_;
  Window window_;

  bool have_xfixes_;
  int xfixes_event_base_;
  int xfixes_error_base_;

  std::unique_ptr<MouseCursor> cursor_shape_;
};

MouseCursorMonitorX11::MouseCursorMonitorX11(
    const DesktopCaptureOptions& options,
    Window window)
    : x_display_(options.x_display()),
      callback_(NULL),
      mode_(SHAPE_AND_POSITION),
      window_(window),
      have_xfixes_(false),
      xfixes_event_base_(-1),
      xfixes_error_base_(-1) {
  // Set a default initial cursor shape in case XFixes is not present.
  const int kSize = 5;
  std::unique_ptr<DesktopFrame> default_cursor(
      new BasicDesktopFrame(DesktopSize(kSize, kSize)));
  const uint8_t pixels[kSize * kSize] = {
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0xff, 0xff, 0xff, 0x00,
    0x00, 0xff, 0xff, 0xff, 0x00,
    0x00, 0xff, 0xff, 0xff, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00
  };
  uint8_t* ptr = default_cursor->data();
  for (int y = 0; y < kSize; ++y) {
    for (int x = 0; x < kSize; ++x) {
      *ptr++ = pixels[kSize * y + x];
      *ptr++ = pixels[kSize * y + x];
      *ptr++ = pixels[kSize * y + x];
      *ptr++ = 0xff;
    }
  }
  DesktopVector hotspot(2, 2);
  cursor_shape_.reset(new MouseCursor(default_cursor.release(), hotspot));
}

MouseCursorMonitorX11::~MouseCursorMonitorX11() {
  if (have_xfixes_) {
    x_display_->RemoveEventHandler(xfixes_event_base_ + XFixesCursorNotify,
                                   this);
  }
}

void MouseCursorMonitorX11::Init(Callback* callback, Mode mode) {
  // Init can be called only once per instance of MouseCursorMonitor.
  RTC_DCHECK(!callback_);
  RTC_DCHECK(callback);

  callback_ = callback;
  mode_ = mode;

  have_xfixes_ =
      XFixesQueryExtension(display(), &xfixes_event_base_, &xfixes_error_base_);

  if (have_xfixes_) {
    // Register for changes to the cursor shape.
    XFixesSelectCursorInput(display(), window_, XFixesDisplayCursorNotifyMask);
    x_display_->AddEventHandler(xfixes_event_base_ + XFixesCursorNotify, this);

    CaptureCursor();
  } else {
    LOG(LS_INFO) << "X server does not support XFixes.";
  }
}

void MouseCursorMonitorX11::Capture() {
  RTC_DCHECK(callback_);

  // Process X11 events in case XFixes has sent cursor notification.
  x_display_->ProcessPendingXEvents();

  // cursor_shape_| is set only if we were notified of a cursor shape change.
  if (cursor_shape_.get())
    callback_->OnMouseCursor(cursor_shape_.release());

  // Get cursor position if necessary.
  if (mode_ == SHAPE_AND_POSITION) {
    int root_x;
    int root_y;
    int win_x;
    int win_y;
    Window root_window;
    Window child_window;
    unsigned int mask;

    XErrorTrap error_trap(display());
    Bool result = XQueryPointer(display(), window_, &root_window, &child_window,
                                &root_x, &root_y, &win_x, &win_y, &mask);
    CursorState state;
    if (!result || error_trap.GetLastErrorAndDisable() != 0) {
      state = OUTSIDE;
    } else {
      // In screen mode (window_ == root_window) the mouse is always inside.
      // XQueryPointer() sets |child_window| to None if the cursor is outside
      // |window_|.
      state =
          (window_ == root_window || child_window != None) ? INSIDE : OUTSIDE;
    }

    callback_->OnMouseCursorPosition(state,
                                     webrtc::DesktopVector(win_x, win_y));
  }
}

bool MouseCursorMonitorX11::HandleXEvent(const XEvent& event) {
  if (have_xfixes_ && event.type == xfixes_event_base_ + XFixesCursorNotify) {
    const XFixesCursorNotifyEvent* cursor_event =
        reinterpret_cast<const XFixesCursorNotifyEvent*>(&event);
    if (cursor_event->subtype == XFixesDisplayCursorNotify) {
      CaptureCursor();
    }
    // Return false, even if the event has been handled, because there might be
    // other listeners for cursor notifications.
  }
  return false;
}

void MouseCursorMonitorX11::CaptureCursor() {
  RTC_DCHECK(have_xfixes_);

  XFixesCursorImage* img;
  {
    XErrorTrap error_trap(display());
    img = XFixesGetCursorImage(display());
    if (!img || error_trap.GetLastErrorAndDisable() != 0)
       return;
   }

   std::unique_ptr<DesktopFrame> image(
       new BasicDesktopFrame(DesktopSize(img->width, img->height)));

  // Xlib stores 32-bit data in longs, even if longs are 64-bits long.
  unsigned long* src = img->pixels;
  uint32_t* dst = reinterpret_cast<uint32_t*>(image->data());
  uint32_t* dst_end = dst + (img->width * img->height);
  while (dst < dst_end) {
    *dst++ = static_cast<uint32_t>(*src++);
  }

  DesktopVector hotspot(std::min(img->width, img->xhot),
                        std::min(img->height, img->yhot));

  XFree(img);

  cursor_shape_.reset(new MouseCursor(image.release(), hotspot));
}

// static
MouseCursorMonitor* MouseCursorMonitor::CreateForWindow(
    const DesktopCaptureOptions& options, WindowId window) {
  if (!options.x_display())
    return NULL;
  window = GetTopLevelWindow(options.x_display()->display(), window);
  if (window == None)
    return NULL;
  return new MouseCursorMonitorX11(options, window);
}

MouseCursorMonitor* MouseCursorMonitor::CreateForScreen(
    const DesktopCaptureOptions& options,
    ScreenId screen) {
  if (!options.x_display())
    return NULL;
  return new MouseCursorMonitorX11(
      options, DefaultRootWindow(options.x_display()->display()));
}

}  // namespace webrtc
<commit_msg>Linux desktopCapture: fix the cursor position issue in Window sharing<commit_after>/*
 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <memory>

#include "webrtc/modules/desktop_capture/mouse_cursor_monitor.h"

#include <X11/extensions/Xfixes.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>

#include "webrtc/base/logging.h"
#include "webrtc/modules/desktop_capture/desktop_capture_options.h"
#include "webrtc/modules/desktop_capture/desktop_frame.h"
#include "webrtc/modules/desktop_capture/mouse_cursor.h"
#include "webrtc/modules/desktop_capture/x11/x_error_trap.h"

namespace {

// WindowCapturer returns window IDs of X11 windows with WM_STATE attribute.
// These windows may not be immediate children of the root window, because
// window managers may re-parent them to add decorations. However,
// XQueryPointer() expects to be passed children of the root. This function
// searches up the list of the windows to find the root child that corresponds
// to |window|.
Window GetTopLevelWindow(Display* display, Window window) {
  while (true) {
    // If the window is in WithdrawnState then look at all of its children.
    ::Window root, parent;
    ::Window *children;
    unsigned int num_children;
    if (!XQueryTree(display, window, &root, &parent, &children,
                    &num_children)) {
      LOG(LS_ERROR) << "Failed to query for child windows although window"
                    << "does not have a valid WM_STATE.";
      return None;
    }
    if (children)
      XFree(children);

    if (parent == root)
      break;

    window = parent;
  }

  return window;
}

}  // namespace

namespace webrtc {

class MouseCursorMonitorX11 : public MouseCursorMonitor,
                              public SharedXDisplay::XEventHandler {
 public:
  MouseCursorMonitorX11(const DesktopCaptureOptions& options, Window window);
  ~MouseCursorMonitorX11() override;

  void Init(Callback* callback, Mode mode) override;
  void Capture() override;

 private:
  // SharedXDisplay::XEventHandler interface.
  bool HandleXEvent(const XEvent& event) override;

  Display* display() { return x_display_->display(); }

  // Captures current cursor shape and stores it in |cursor_shape_|.
  void CaptureCursor();

  rtc::scoped_refptr<SharedXDisplay> x_display_;
  Callback* callback_;
  Mode mode_;
  Window window_;

  bool have_xfixes_;
  int xfixes_event_base_;
  int xfixes_error_base_;

  std::unique_ptr<MouseCursor> cursor_shape_;
};

MouseCursorMonitorX11::MouseCursorMonitorX11(
    const DesktopCaptureOptions& options,
    Window window)
    : x_display_(options.x_display()),
      callback_(NULL),
      mode_(SHAPE_AND_POSITION),
      window_(window),
      have_xfixes_(false),
      xfixes_event_base_(-1),
      xfixes_error_base_(-1) {
  // Set a default initial cursor shape in case XFixes is not present.
  const int kSize = 5;
  std::unique_ptr<DesktopFrame> default_cursor(
      new BasicDesktopFrame(DesktopSize(kSize, kSize)));
  const uint8_t pixels[kSize * kSize] = {
    0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0xff, 0xff, 0xff, 0x00,
    0x00, 0xff, 0xff, 0xff, 0x00,
    0x00, 0xff, 0xff, 0xff, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00
  };
  uint8_t* ptr = default_cursor->data();
  for (int y = 0; y < kSize; ++y) {
    for (int x = 0; x < kSize; ++x) {
      *ptr++ = pixels[kSize * y + x];
      *ptr++ = pixels[kSize * y + x];
      *ptr++ = pixels[kSize * y + x];
      *ptr++ = 0xff;
    }
  }
  DesktopVector hotspot(2, 2);
  cursor_shape_.reset(new MouseCursor(default_cursor.release(), hotspot));
}

MouseCursorMonitorX11::~MouseCursorMonitorX11() {
  if (have_xfixes_) {
    x_display_->RemoveEventHandler(xfixes_event_base_ + XFixesCursorNotify,
                                   this);
  }
}

void MouseCursorMonitorX11::Init(Callback* callback, Mode mode) {
  // Init can be called only once per instance of MouseCursorMonitor.
  RTC_DCHECK(!callback_);
  RTC_DCHECK(callback);

  callback_ = callback;
  mode_ = mode;

  have_xfixes_ =
      XFixesQueryExtension(display(), &xfixes_event_base_, &xfixes_error_base_);

  if (have_xfixes_) {
    // Register for changes to the cursor shape.
    XFixesSelectCursorInput(display(), window_, XFixesDisplayCursorNotifyMask);
    x_display_->AddEventHandler(xfixes_event_base_ + XFixesCursorNotify, this);

    CaptureCursor();
  } else {
    LOG(LS_INFO) << "X server does not support XFixes.";
  }
}

void MouseCursorMonitorX11::Capture() {
  RTC_DCHECK(callback_);

  // Process X11 events in case XFixes has sent cursor notification.
  x_display_->ProcessPendingXEvents();

  // cursor_shape_| is set only if we were notified of a cursor shape change.
  if (cursor_shape_.get())
    callback_->OnMouseCursor(cursor_shape_.release());

  // Get cursor position if necessary.
  if (mode_ == SHAPE_AND_POSITION) {
    int root_x;
    int root_y;
    int win_x;
    int win_y;
    Window root_window;
    Window child_window;
    unsigned int mask;

    XErrorTrap error_trap(display());
    Bool result = XQueryPointer(display(), window_, &root_window, &child_window,
                                &root_x, &root_y, &win_x, &win_y, &mask);
    CursorState state;
    if (!result || error_trap.GetLastErrorAndDisable() != 0) {
      state = OUTSIDE;
    } else {
      // In screen mode (window_ == root_window) the mouse is always inside.
      // XQueryPointer() sets |child_window| to None if the cursor is outside
      // |window_|.
      state =
          (window_ == root_window || child_window != None) ? INSIDE : OUTSIDE;
    }

    // As the comments to GetTopLevelWindow() above indicate, in window capture,
    // the cursor position capture happens in |window_|, while the frame catpure
    // happens in |child_window|. These two windows are not alwyas same, as
    // window manager may add some decorations to the |window_|. So translate
    // the coordinate in |window_| to the coordinate space of |child_window|.
    if (window_ != root_window && state == INSIDE) {
      int translated_x, translated_y;
      Window unused;
      if (XTranslateCoordinates(display(), window_, child_window, win_x, win_y,
                                &translated_x, &translated_y, &unused)) {
        win_x = translated_x;
        win_y = translated_y;
      }
    }

    callback_->OnMouseCursorPosition(state,
                                     webrtc::DesktopVector(win_x, win_y));
  }
}

bool MouseCursorMonitorX11::HandleXEvent(const XEvent& event) {
  if (have_xfixes_ && event.type == xfixes_event_base_ + XFixesCursorNotify) {
    const XFixesCursorNotifyEvent* cursor_event =
        reinterpret_cast<const XFixesCursorNotifyEvent*>(&event);
    if (cursor_event->subtype == XFixesDisplayCursorNotify) {
      CaptureCursor();
    }
    // Return false, even if the event has been handled, because there might be
    // other listeners for cursor notifications.
  }
  return false;
}

void MouseCursorMonitorX11::CaptureCursor() {
  RTC_DCHECK(have_xfixes_);

  XFixesCursorImage* img;
  {
    XErrorTrap error_trap(display());
    img = XFixesGetCursorImage(display());
    if (!img || error_trap.GetLastErrorAndDisable() != 0)
       return;
   }

   std::unique_ptr<DesktopFrame> image(
       new BasicDesktopFrame(DesktopSize(img->width, img->height)));

  // Xlib stores 32-bit data in longs, even if longs are 64-bits long.
  unsigned long* src = img->pixels;
  uint32_t* dst = reinterpret_cast<uint32_t*>(image->data());
  uint32_t* dst_end = dst + (img->width * img->height);
  while (dst < dst_end) {
    *dst++ = static_cast<uint32_t>(*src++);
  }

  DesktopVector hotspot(std::min(img->width, img->xhot),
                        std::min(img->height, img->yhot));

  XFree(img);

  cursor_shape_.reset(new MouseCursor(image.release(), hotspot));
}

// static
MouseCursorMonitor* MouseCursorMonitor::CreateForWindow(
    const DesktopCaptureOptions& options, WindowId window) {
  if (!options.x_display())
    return NULL;
  window = GetTopLevelWindow(options.x_display()->display(), window);
  if (window == None)
    return NULL;
  return new MouseCursorMonitorX11(options, window);
}

MouseCursorMonitor* MouseCursorMonitor::CreateForScreen(
    const DesktopCaptureOptions& options,
    ScreenId screen) {
  if (!options.x_display())
    return NULL;
  return new MouseCursorMonitorX11(
      options, DefaultRootWindow(options.x_display()->display()));
}

}  // namespace webrtc
<|endoftext|>