<commit_before>#include "qt/create_feature_dialog.hpp"
#include "qt/draw_widget.hpp"
#include "qt/editor_dialog.hpp"
#include "qt/place_page_dialog.hpp"
#include "qt/qt_common/helpers.hpp"
#include "qt/qt_common/scale_slider.hpp"

#include "map/framework.hpp"

#include "drape_frontend/visual_params.hpp"

#include "search/result.hpp"

#include "storage/index.hpp"

#include "indexer/editable_map_object.hpp"

#include "platform/settings.hpp"
#include "platform/platform.hpp"
#include "platform/settings.hpp"

#include <QtGui/QMouseEvent>
#include <QtGui/QGuiApplication>

#include <QtWidgets/QApplication>
#include <QtWidgets/QDesktopWidget>
#include <QtWidgets/QDialogButtonBox>
#include <QtWidgets/QMenu>

#include <QtCore/QLocale>
#include <QtCore/QDateTime>
#include <QtCore/QThread>
#include <QtCore/QTimer>

using namespace qt::common;

namespace qt
{
DrawWidget::DrawWidget(Framework & framework, bool apiOpenGLES3, QWidget * parent)
  : TBase(framework, apiOpenGLES3, parent)
  , m_rubberBand(nullptr)
  , m_emulatingLocation(false)
{
  m_framework.SetMapSelectionListeners(
      [this](place_page::Info const & info) { ShowPlacePage(info); },
      [](bool /* switchFullScreenMode */) {});  // Empty deactivation listener.

  m_framework.GetRoutingManager().SetRouteBuildingListener(
      [](routing::IRouter::ResultCode, storage::TCountriesVec const &) {});

  m_framework.SetCurrentCountryChangedListener([this](storage::TCountryId const & countryId) {
    m_countryId = countryId;
    UpdateCountryStatus(countryId);
  });

  QTimer * countryStatusTimer = new QTimer(this);
  VERIFY(connect(countryStatusTimer, SIGNAL(timeout()), this, SLOT(OnUpdateCountryStatusByTimer())), ());
  countryStatusTimer->setSingleShot(false);
  countryStatusTimer->start(1000);
}

DrawWidget::~DrawWidget()
{
  delete m_rubberBand;
}

void DrawWidget::UpdateCountryStatus(storage::TCountryId const & countryId)
{
  if (m_currentCountryChanged != nullptr)
  {
    string countryName = countryId;
    auto status = m_framework.GetStorage().CountryStatusEx(countryId);

    uint8_t progressInPercentage = 0;
    storage::MapFilesDownloader::TProgress progressInByte = make_pair(0, 0);
    if (!countryId.empty())
    {
      storage::NodeAttrs nodeAttrs;
      m_framework.GetStorage().GetNodeAttrs(countryId, nodeAttrs);
      progressInByte = nodeAttrs.m_downloadingProgress;
      if (progressInByte.second != 0)
        progressInPercentage = static_cast<int8_t>(100 * progressInByte.first / progressInByte.second);
    }

    m_currentCountryChanged(countryId, countryName, status,
                            progressInByte.second, progressInPercentage);
  }
}

void DrawWidget::OnUpdateCountryStatusByTimer()
{
  if (!m_countryId.empty())
    UpdateCountryStatus(m_countryId);
}

void DrawWidget::SetCurrentCountryChangedListener(DrawWidget::TCurrentCountryChanged const & listener)
{
  m_currentCountryChanged = listener;
}

void DrawWidget::DownloadCountry(storage::TCountryId const & countryId)
{
  m_framework.GetStorage().DownloadNode(countryId);
  if (!m_countryId.empty())
    UpdateCountryStatus(m_countryId);
}

void DrawWidget::RetryToDownloadCountry(storage::TCountryId const & countryId)
{
  // TODO @bykoianko
}

void DrawWidget::PrepareShutdown()
{
}

void DrawWidget::UpdateAfterSettingsChanged()
{
  m_framework.EnterForeground();
}

void DrawWidget::ShowAll()
{
  m_framework.ShowAll();
}

void DrawWidget::ChoosePositionModeEnable()
{
  m_framework.BlockTapEvents(true /* block */);
  m_framework.EnableChoosePositionMode(true /* enable */, false /* enableBounds */,
                                       false /* applyPosition */, m2::PointD() /* position */);
}

void DrawWidget::ChoosePositionModeDisable()
{
  m_framework.EnableChoosePositionMode(false /* enable */, false /* enableBounds */,
                                       false /* applyPosition */, m2::PointD() /* position */);
  m_framework.BlockTapEvents(false /* block */);
}

void DrawWidget::initializeGL()
{
  MapWidget::initializeGL();
  m_framework.LoadBookmarks();
}

void DrawWidget::mousePressEvent(QMouseEvent * e)
{
  QOpenGLWidget::mousePressEvent(e);

  m2::PointD const pt = GetDevicePoint(e);

  if (IsLeftButton(e))
  {
    if (IsShiftModifier(e))
      SubmitRoutingPoint(pt);
    else if (IsAltModifier(e))
      SubmitFakeLocationPoint(pt);
    else
      m_framework.TouchEvent(GetTouchEvent(e, df::TouchEvent::TOUCH_DOWN));
  }
  else if (IsRightButton(e))
  {
    if (!m_selectionMode || IsCommandModifier(e))
    {
      ShowInfoPopup(e, pt);
    }
    else
    {
      m_rubberBandOrigin = e->pos();
      if (m_rubberBand == nullptr)
        m_rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
      m_rubberBand->setGeometry(QRect(m_rubberBandOrigin, QSize()));
      m_rubberBand->show();
    }
  }
}

void DrawWidget::mouseMoveEvent(QMouseEvent * e)
{
  QOpenGLWidget::mouseMoveEvent(e);
  if (IsLeftButton(e) && !IsAltModifier(e))
    m_framework.TouchEvent(GetTouchEvent(e, df::TouchEvent::TOUCH_MOVE));

  if (m_selectionMode && m_rubberBand != nullptr && m_rubberBand->isVisible())
  {
    m_rubberBand->setGeometry(QRect(m_rubberBandOrigin, e->pos()).normalized());
  }
}

void DrawWidget::mouseReleaseEvent(QMouseEvent * e)
{
  QOpenGLWidget::mouseReleaseEvent(e);
  if (IsLeftButton(e) && !IsAltModifier(e))
  {
    m_framework.TouchEvent(GetTouchEvent(e, df::TouchEvent::TOUCH_UP));
  }
  else if (m_selectionMode && IsRightButton(e) && m_rubberBand != nullptr &&
           m_rubberBand->isVisible())
  {
    QPoint const lt = m_rubberBand->geometry().topLeft();
    QPoint const rb = m_rubberBand->geometry().bottomRight();
    m2::RectD rect;
    rect.Add(m_framework.PtoG(m2::PointD(L2D(lt.x()), L2D(lt.y()))));
    rect.Add(m_framework.PtoG(m2::PointD(L2D(rb.x()), L2D(rb.y()))));
    m_framework.VisualizeRoadsInRect(rect);
    m_rubberBand->hide();
  }
}

void DrawWidget::keyPressEvent(QKeyEvent * e)
{
  TBase::keyPressEvent(e);
  if (IsLeftButton(QGuiApplication::mouseButtons()) &&
      e->key() == Qt::Key_Control)
  {
    df::TouchEvent event;
    event.SetTouchType(df::TouchEvent::TOUCH_DOWN);
    df::Touch touch;
    touch.m_id = 0;
    touch.m_location = m2::PointD(L2D(QCursor::pos().x()), L2D(QCursor::pos().y()));
    event.SetFirstTouch(touch);
    event.SetSecondTouch(GetSymmetrical(touch));

    m_framework.TouchEvent(event);
  }
}

void DrawWidget::keyReleaseEvent(QKeyEvent * e)
{
  TBase::keyReleaseEvent(e);

  if (IsLeftButton(QGuiApplication::mouseButtons()) &&
      e->key() == Qt::Key_Control)
  {
    df::TouchEvent event;
    event.SetTouchType(df::TouchEvent::TOUCH_UP);
    df::Touch touch;
    touch.m_id = 0;
    touch.m_location = m2::PointD(L2D(QCursor::pos().x()), L2D(QCursor::pos().y()));
    event.SetFirstTouch(touch);
    event.SetSecondTouch(GetSymmetrical(touch));

    m_framework.TouchEvent(event);
  }
  else if (e->key() == Qt::Key_Alt)
    m_emulatingLocation = false;
}

bool DrawWidget::Search(search::EverywhereSearchParams const & params)
{
  return m_framework.SearchEverywhere(params);
}

string DrawWidget::GetDistance(search::Result const & res) const
{
  string dist;
  double lat, lon;
  if (m_framework.GetCurrentPosition(lat, lon))
  {
    double dummy;
    (void) m_framework.GetDistanceAndAzimut(res.GetFeatureCenter(), lat, lon, -1.0, dist, dummy);
  }
  return dist;
}

void DrawWidget::ShowSearchResult(search::Result const & res)
{
  m_framework.ShowSearchResult(res);
}

void DrawWidget::CreateFeature()
{
  auto cats = m_framework.GetEditorCategories();
  CreateFeatureDialog dlg(this, cats);
  if (dlg.exec() == QDialog::Accepted)
  {
    osm::EditableMapObject emo;
    if (m_framework.CreateMapObject(m_framework.GetViewportCenter(), dlg.GetSelectedType(), emo))
    {
      EditorDialog dlg(this, emo);
      int const result = dlg.exec();
      if (result == QDialog::Accepted)
        m_framework.SaveEditedMapObject(emo);
    }
    else
    {
      LOG(LWARNING, ("Error creating new map object."));
    }
  }
}

void DrawWidget::OnLocationUpdate(location::GpsInfo const & info)
{
  if (!m_emulatingLocation)
    m_framework.OnLocationUpdate(info);
}

void DrawWidget::SetMapStyle(MapStyle mapStyle)
{
  m_framework.SetMapStyle(mapStyle);
}

void DrawWidget::SubmitFakeLocationPoint(m2::PointD const & pt)
{
  m_emulatingLocation = true;
  m2::PointD const point = m_framework.P3dtoG(pt);

  location::GpsInfo info;
  info.m_latitude = MercatorBounds::YToLat(point.y);
  info.m_longitude = MercatorBounds::XToLon(point.x);
  info.m_horizontalAccuracy = 10;
  info.m_timestamp = QDateTime::currentMSecsSinceEpoch() / 1000.0;

  m_framework.OnLocationUpdate(info);

  if (m_framework.GetRoutingManager().IsRoutingActive())
  {
    location::FollowingInfo loc;
    m_framework.GetRoutingManager().GetRouteFollowingInfo(loc);
    LOG(LDEBUG, ("Distance:", loc.m_distToTarget, loc.m_targetUnitsSuffix, "Time:", loc.m_time,
                 "Turn:", routing::turns::GetTurnString(loc.m_turn), "(", loc.m_distToTurn, loc.m_turnUnitsSuffix,
                 ") Roundabout exit number:", loc.m_exitNum));
  }
}

void DrawWidget::SubmitRoutingPoint(m2::PointD const & pt)
{
  auto & routingManager = m_framework.GetRoutingManager();
  std::vector<RouteMarkData> points = routingManager.GetRoutePoints();
  auto const pointsCount = points.size();

  // Check if limit of intermediate points is reached.
  if (m_routePointAddMode == RouteMarkType::Intermediate && !routingManager.CouldAddIntermediatePoint())
    routingManager.RemoveRoutePoint(RouteMarkType::Intermediate, 0);

  // Insert implicit start point.
  if (m_routePointAddMode == RouteMarkType::Finish && pointsCount == 0)
  {
    RouteMarkData startPoint;
    startPoint.m_pointType = RouteMarkType::Start;
    startPoint.m_isMyPosition = true;
    routingManager.AddRoutePoint(std::move(startPoint));
  }

  RouteMarkData point;
  point.m_pointType = m_routePointAddMode;
  point.m_isMyPosition = false;
  point.m_position = m_framework.P3dtoG(pt);
  routingManager.AddRoutePoint(std::move(point));

  if (routingManager.GetRoutePoints().size() >= 2)
    routingManager.BuildRoute(0 /* timeoutSec */);
}

void DrawWidget::FollowRoute()
{
  auto & routingManager = m_framework.GetRoutingManager();
  if (routingManager.IsRoutingActive() && !routingManager.IsRoutingFollowing())
    routingManager.FollowRoute();
}

void DrawWidget::ClearRoute()
{
  m_framework.GetRoutingManager().CloseRouting(true /* remove route points */);
}

void DrawWidget::ShowPlacePage(place_page::Info const & info)
{
  search::AddressInfo address;
  if (info.IsFeature())
    address = m_framework.GetFeatureAddressInfo(info.GetID());
  else
    address = m_framework.GetAddressInfoAtPoint(info.GetMercator());

  PlacePageDialog dlg(this, info, address);
  if (dlg.exec() == QDialog::Accepted)
  {
    osm::EditableMapObject emo;
    if (m_framework.GetEditableMapObject(info.GetID(), emo))
    {
      EditorDialog dlg(this, emo);
      int const result = dlg.exec();
      if (result == QDialog::Accepted)
      {
        m_framework.SaveEditedMapObject(emo);
        m_framework.UpdatePlacePageInfoForCurrentSelection();
      }
      else if (result == QDialogButtonBox::DestructiveRole)
      {
        m_framework.DeleteFeature(info.GetID());
      }
    }
    else
    {
      LOG(LERROR, ("Error while trying to edit feature."));
    }
  }
  m_framework.DeactivateMapSelection(false);
}

void DrawWidget::ShowInfoPopup(QMouseEvent * e, m2::PointD const & pt)
{
  // show feature types
  QMenu menu;
  auto const addStringFn = [&menu](string const & s)
  {
    menu.addAction(QString::fromUtf8(s.c_str()));
  };

  m_framework.ForEachFeatureAtPoint([&](FeatureType & ft)
  {
    search::AddressInfo const info = m_framework.GetFeatureAddressInfo(ft);

    string concat;
    for (auto const & type : info.m_types)
      concat += type + " ";
    addStringFn(concat);

    if (!info.m_name.empty())
      addStringFn(info.m_name);

    string const addr = info.FormatAddress();
    if (!addr.empty())
      addStringFn(addr);

    menu.addSeparator();
  }, m_framework.PtoG(pt));

  menu.exec(e->pos());
}

void DrawWidget::SetRouter(routing::RouterType routerType)
{
  m_framework.GetRoutingManager().SetRouter(routerType);
}

void DrawWidget::SetSelectionMode(bool mode) { m_selectionMode = mode; }

// static
void DrawWidget::SetDefaultSurfaceFormat(bool apiOpenGLES3)
{
  QSurfaceFormat fmt;
  fmt.setAlphaBufferSize(8);
  fmt.setBlueBufferSize(8);
  fmt.setGreenBufferSize(8);
  fmt.setRedBufferSize(8);
  fmt.setStencilBufferSize(0);
  fmt.setSamples(0);
  fmt.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
  fmt.setSwapInterval(1);
  fmt.setDepthBufferSize(16);
  if (apiOpenGLES3)
  {
    fmt.setProfile(QSurfaceFormat::CoreProfile);
    fmt.setVersion(3, 2);
  }
  else
  {
    fmt.setProfile(QSurfaceFormat::CompatibilityProfile);
    fmt.setVersion(2, 1);
  }
  //fmt.setOption(QSurfaceFormat::DebugContext);
  QSurfaceFormat::setDefaultFormat(fmt);
}
}  // namespace qt
<commit_msg>Review fixes<commit_after>#include "qt/create_feature_dialog.hpp"
#include "qt/draw_widget.hpp"
#include "qt/editor_dialog.hpp"
#include "qt/place_page_dialog.hpp"
#include "qt/qt_common/helpers.hpp"
#include "qt/qt_common/scale_slider.hpp"

#include "map/framework.hpp"

#include "drape_frontend/visual_params.hpp"

#include "search/result.hpp"

#include "storage/index.hpp"

#include "indexer/editable_map_object.hpp"

#include "platform/settings.hpp"
#include "platform/platform.hpp"
#include "platform/settings.hpp"

#include <QtGui/QMouseEvent>
#include <QtGui/QGuiApplication>

#include <QtWidgets/QApplication>
#include <QtWidgets/QDesktopWidget>
#include <QtWidgets/QDialogButtonBox>
#include <QtWidgets/QMenu>

#include <QtCore/QLocale>
#include <QtCore/QDateTime>
#include <QtCore/QThread>
#include <QtCore/QTimer>

using namespace qt::common;

namespace qt
{
DrawWidget::DrawWidget(Framework & framework, bool apiOpenGLES3, QWidget * parent)
  : TBase(framework, apiOpenGLES3, parent)
  , m_rubberBand(nullptr)
  , m_emulatingLocation(false)
{
  m_framework.SetMapSelectionListeners(
      [this](place_page::Info const & info) { ShowPlacePage(info); },
      [](bool /* switchFullScreenMode */) {});  // Empty deactivation listener.

  m_framework.GetRoutingManager().SetRouteBuildingListener(
      [](routing::IRouter::ResultCode, storage::TCountriesVec const &) {});

  m_framework.SetCurrentCountryChangedListener([this](storage::TCountryId const & countryId) {
    m_countryId = countryId;
    UpdateCountryStatus(countryId);
  });

  QTimer * countryStatusTimer = new QTimer(this);
  VERIFY(connect(countryStatusTimer, SIGNAL(timeout()), this, SLOT(OnUpdateCountryStatusByTimer())), ());
  countryStatusTimer->setSingleShot(false);
  countryStatusTimer->start(1000);
}

DrawWidget::~DrawWidget()
{
  delete m_rubberBand;
}

void DrawWidget::UpdateCountryStatus(storage::TCountryId const & countryId)
{
  if (m_currentCountryChanged != nullptr)
  {
    string countryName = countryId;
    auto status = m_framework.GetStorage().CountryStatusEx(countryId);

    uint8_t progressInPercentage = 0;
    storage::MapFilesDownloader::TProgress progressInByte = make_pair(0, 0);
    if (!countryId.empty())
    {
      storage::NodeAttrs nodeAttrs;
      m_framework.GetStorage().GetNodeAttrs(countryId, nodeAttrs);
      progressInByte = nodeAttrs.m_downloadingProgress;
      if (progressInByte.second != 0)
        progressInPercentage = static_cast<int8_t>(100 * progressInByte.first / progressInByte.second);
    }

    m_currentCountryChanged(countryId, countryName, status,
                            progressInByte.second, progressInPercentage);
  }
}

void DrawWidget::OnUpdateCountryStatusByTimer()
{
  if (!m_countryId.empty())
    UpdateCountryStatus(m_countryId);
}

void DrawWidget::SetCurrentCountryChangedListener(DrawWidget::TCurrentCountryChanged const & listener)
{
  m_currentCountryChanged = listener;
}

void DrawWidget::DownloadCountry(storage::TCountryId const & countryId)
{
  m_framework.GetStorage().DownloadNode(countryId);
  if (!m_countryId.empty())
    UpdateCountryStatus(m_countryId);
}

void DrawWidget::RetryToDownloadCountry(storage::TCountryId const & countryId)
{
  // TODO @bykoianko
}

void DrawWidget::PrepareShutdown()
{
}

void DrawWidget::UpdateAfterSettingsChanged()
{
  m_framework.EnterForeground();
}

void DrawWidget::ShowAll()
{
  m_framework.ShowAll();
}

void DrawWidget::ChoosePositionModeEnable()
{
  m_framework.BlockTapEvents(true /* block */);
  m_framework.EnableChoosePositionMode(true /* enable */, false /* enableBounds */,
                                       false /* applyPosition */, m2::PointD() /* position */);
}

void DrawWidget::ChoosePositionModeDisable()
{
  m_framework.EnableChoosePositionMode(false /* enable */, false /* enableBounds */,
                                       false /* applyPosition */, m2::PointD() /* position */);
  m_framework.BlockTapEvents(false /* block */);
}

void DrawWidget::initializeGL()
{
  MapWidget::initializeGL();
  m_framework.LoadBookmarks();
}

void DrawWidget::mousePressEvent(QMouseEvent * e)
{
  QOpenGLWidget::mousePressEvent(e);

  m2::PointD const pt = GetDevicePoint(e);

  if (IsLeftButton(e))
  {
    if (IsShiftModifier(e))
      SubmitRoutingPoint(pt);
    else if (IsAltModifier(e))
      SubmitFakeLocationPoint(pt);
    else
      m_framework.TouchEvent(GetTouchEvent(e, df::TouchEvent::TOUCH_DOWN));
  }
  else if (IsRightButton(e))
  {
    if (!m_selectionMode || IsCommandModifier(e))
    {
      ShowInfoPopup(e, pt);
    }
    else
    {
      m_rubberBandOrigin = e->pos();
      if (m_rubberBand == nullptr)
        m_rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
      m_rubberBand->setGeometry(QRect(m_rubberBandOrigin, QSize()));
      m_rubberBand->show();
    }
  }
}

void DrawWidget::mouseMoveEvent(QMouseEvent * e)
{
  QOpenGLWidget::mouseMoveEvent(e);
  if (IsLeftButton(e) && !IsAltModifier(e))
    m_framework.TouchEvent(GetTouchEvent(e, df::TouchEvent::TOUCH_MOVE));

  if (m_selectionMode && m_rubberBand != nullptr && m_rubberBand->isVisible())
  {
    m_rubberBand->setGeometry(QRect(m_rubberBandOrigin, e->pos()).normalized());
  }
}

void DrawWidget::mouseReleaseEvent(QMouseEvent * e)
{
  QOpenGLWidget::mouseReleaseEvent(e);
  if (IsLeftButton(e) && !IsAltModifier(e))
  {
    m_framework.TouchEvent(GetTouchEvent(e, df::TouchEvent::TOUCH_UP));
  }
  else if (m_selectionMode && IsRightButton(e) && m_rubberBand != nullptr &&
           m_rubberBand->isVisible())
  {
    QPoint const lt = m_rubberBand->geometry().topLeft();
    QPoint const rb = m_rubberBand->geometry().bottomRight();
    m2::RectD rect;
    rect.Add(m_framework.PtoG(m2::PointD(L2D(lt.x()), L2D(lt.y()))));
    rect.Add(m_framework.PtoG(m2::PointD(L2D(rb.x()), L2D(rb.y()))));
    m_framework.VisualizeRoadsInRect(rect);
    m_rubberBand->hide();
  }
}

void DrawWidget::keyPressEvent(QKeyEvent * e)
{
  TBase::keyPressEvent(e);
  if (IsLeftButton(QGuiApplication::mouseButtons()) &&
      e->key() == Qt::Key_Control)
  {
    df::TouchEvent event;
    event.SetTouchType(df::TouchEvent::TOUCH_DOWN);
    df::Touch touch;
    touch.m_id = 0;
    touch.m_location = m2::PointD(L2D(QCursor::pos().x()), L2D(QCursor::pos().y()));
    event.SetFirstTouch(touch);
    event.SetSecondTouch(GetSymmetrical(touch));

    m_framework.TouchEvent(event);
  }
}

void DrawWidget::keyReleaseEvent(QKeyEvent * e)
{
  TBase::keyReleaseEvent(e);

  if (IsLeftButton(QGuiApplication::mouseButtons()) &&
      e->key() == Qt::Key_Control)
  {
    df::TouchEvent event;
    event.SetTouchType(df::TouchEvent::TOUCH_UP);
    df::Touch touch;
    touch.m_id = 0;
    touch.m_location = m2::PointD(L2D(QCursor::pos().x()), L2D(QCursor::pos().y()));
    event.SetFirstTouch(touch);
    event.SetSecondTouch(GetSymmetrical(touch));

    m_framework.TouchEvent(event);
  }
  else if (e->key() == Qt::Key_Alt)
    m_emulatingLocation = false;
}

bool DrawWidget::Search(search::EverywhereSearchParams const & params)
{
  return m_framework.SearchEverywhere(params);
}

string DrawWidget::GetDistance(search::Result const & res) const
{
  string dist;
  double lat, lon;
  if (m_framework.GetCurrentPosition(lat, lon))
  {
    double dummy;
    (void) m_framework.GetDistanceAndAzimut(res.GetFeatureCenter(), lat, lon, -1.0, dist, dummy);
  }
  return dist;
}

void DrawWidget::ShowSearchResult(search::Result const & res)
{
  m_framework.ShowSearchResult(res);
}

void DrawWidget::CreateFeature()
{
  auto cats = m_framework.GetEditorCategories();
  CreateFeatureDialog dlg(this, cats);
  if (dlg.exec() == QDialog::Accepted)
  {
    osm::EditableMapObject emo;
    if (m_framework.CreateMapObject(m_framework.GetViewportCenter(), dlg.GetSelectedType(), emo))
    {
      EditorDialog dlg(this, emo);
      int const result = dlg.exec();
      if (result == QDialog::Accepted)
        m_framework.SaveEditedMapObject(emo);
    }
    else
    {
      LOG(LWARNING, ("Error creating new map object."));
    }
  }
}

void DrawWidget::OnLocationUpdate(location::GpsInfo const & info)
{
  if (!m_emulatingLocation)
    m_framework.OnLocationUpdate(info);
}

void DrawWidget::SetMapStyle(MapStyle mapStyle)
{
  m_framework.SetMapStyle(mapStyle);
}

void DrawWidget::SubmitFakeLocationPoint(m2::PointD const & pt)
{
  m_emulatingLocation = true;
  m2::PointD const point = m_framework.P3dtoG(pt);

  location::GpsInfo info;
  info.m_latitude = MercatorBounds::YToLat(point.y);
  info.m_longitude = MercatorBounds::XToLon(point.x);
  info.m_horizontalAccuracy = 10;
  info.m_timestamp = QDateTime::currentMSecsSinceEpoch() / 1000.0;

  m_framework.OnLocationUpdate(info);

  if (m_framework.GetRoutingManager().IsRoutingActive())
  {
    location::FollowingInfo loc;
    m_framework.GetRoutingManager().GetRouteFollowingInfo(loc);
    LOG(LDEBUG, ("Distance:", loc.m_distToTarget, loc.m_targetUnitsSuffix, "Time:", loc.m_time,
                 "Turn:", routing::turns::GetTurnString(loc.m_turn), "(", loc.m_distToTurn, loc.m_turnUnitsSuffix,
                 ") Roundabout exit number:", loc.m_exitNum));
  }
}

void DrawWidget::SubmitRoutingPoint(m2::PointD const & pt)
{
  auto & routingManager = m_framework.GetRoutingManager();
  auto const pointsCount = routingManager.GetRoutePoints().size();

  // Check if limit of intermediate points is reached.
  if (m_routePointAddMode == RouteMarkType::Intermediate && !routingManager.CouldAddIntermediatePoint())
    routingManager.RemoveRoutePoint(RouteMarkType::Intermediate, 0);

  // Insert implicit start point.
  if (m_routePointAddMode == RouteMarkType::Finish && pointsCount == 0)
  {
    RouteMarkData startPoint;
    startPoint.m_pointType = RouteMarkType::Start;
    startPoint.m_isMyPosition = true;
    routingManager.AddRoutePoint(std::move(startPoint));
  }

  RouteMarkData point;
  point.m_pointType = m_routePointAddMode;
  point.m_isMyPosition = false;
  point.m_position = m_framework.P3dtoG(pt);
  routingManager.AddRoutePoint(std::move(point));

  if (routingManager.GetRoutePoints().size() >= 2)
    routingManager.BuildRoute(0 /* timeoutSec */);
}

void DrawWidget::FollowRoute()
{
  auto & routingManager = m_framework.GetRoutingManager();
  if (routingManager.IsRoutingActive() && !routingManager.IsRoutingFollowing())
    routingManager.FollowRoute();
}

void DrawWidget::ClearRoute()
{
  m_framework.GetRoutingManager().CloseRouting(true /* remove route points */);
}

void DrawWidget::ShowPlacePage(place_page::Info const & info)
{
  search::AddressInfo address;
  if (info.IsFeature())
    address = m_framework.GetFeatureAddressInfo(info.GetID());
  else
    address = m_framework.GetAddressInfoAtPoint(info.GetMercator());

  PlacePageDialog dlg(this, info, address);
  if (dlg.exec() == QDialog::Accepted)
  {
    osm::EditableMapObject emo;
    if (m_framework.GetEditableMapObject(info.GetID(), emo))
    {
      EditorDialog dlg(this, emo);
      int const result = dlg.exec();
      if (result == QDialog::Accepted)
      {
        m_framework.SaveEditedMapObject(emo);
        m_framework.UpdatePlacePageInfoForCurrentSelection();
      }
      else if (result == QDialogButtonBox::DestructiveRole)
      {
        m_framework.DeleteFeature(info.GetID());
      }
    }
    else
    {
      LOG(LERROR, ("Error while trying to edit feature."));
    }
  }
  m_framework.DeactivateMapSelection(false);
}

void DrawWidget::ShowInfoPopup(QMouseEvent * e, m2::PointD const & pt)
{
  // show feature types
  QMenu menu;
  auto const addStringFn = [&menu](string const & s)
  {
    menu.addAction(QString::fromUtf8(s.c_str()));
  };

  m_framework.ForEachFeatureAtPoint([&](FeatureType & ft)
  {
    search::AddressInfo const info = m_framework.GetFeatureAddressInfo(ft);

    string concat;
    for (auto const & type : info.m_types)
      concat += type + " ";
    addStringFn(concat);

    if (!info.m_name.empty())
      addStringFn(info.m_name);

    string const addr = info.FormatAddress();
    if (!addr.empty())
      addStringFn(addr);

    menu.addSeparator();
  }, m_framework.PtoG(pt));

  menu.exec(e->pos());
}

void DrawWidget::SetRouter(routing::RouterType routerType)
{
  m_framework.GetRoutingManager().SetRouter(routerType);
}

void DrawWidget::SetSelectionMode(bool mode) { m_selectionMode = mode; }

// static
void DrawWidget::SetDefaultSurfaceFormat(bool apiOpenGLES3)
{
  QSurfaceFormat fmt;
  fmt.setAlphaBufferSize(8);
  fmt.setBlueBufferSize(8);
  fmt.setGreenBufferSize(8);
  fmt.setRedBufferSize(8);
  fmt.setStencilBufferSize(0);
  fmt.setSamples(0);
  fmt.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
  fmt.setSwapInterval(1);
  fmt.setDepthBufferSize(16);
  if (apiOpenGLES3)
  {
    fmt.setProfile(QSurfaceFormat::CoreProfile);
    fmt.setVersion(3, 2);
  }
  else
  {
    fmt.setProfile(QSurfaceFormat::CompatibilityProfile);
    fmt.setVersion(2, 1);
  }
  //fmt.setOption(QSurfaceFormat::DebugContext);
  QSurfaceFormat::setDefaultFormat(fmt);
}
}  // namespace qt
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All rights reserved
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// +build ignore

#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>

#include "ast.h"
#include "dep.h"
#include "eval.h"
#include "exec.h"
#include "file.h"
#include "file_cache.h"
#include "fileutil.h"
#include "find.h"
#include "flags.h"
#include "func.h"
#include "log.h"
#include "ninja.h"
#include "parser.h"
#include "stats.h"
#include "string_piece.h"
#include "stringprintf.h"
#include "strutil.h"
#include "symtab.h"
#include "timeutil.h"
#include "var.h"

static const char* g_makefile;
static bool g_is_syntax_check_only;
static bool g_generate_ninja;
static bool g_regen;
static const char* g_ninja_suffix;
static const char* g_ninja_dir;
static bool g_use_find_emulator;

static bool ParseCommandLineOptionWithArg(StringPiece option,
                                          char* argv[],
                                          int* index,
                                          const char** out_arg) {
  const char* arg = argv[*index];
  if (!HasPrefix(arg, option))
    return false;
  if (arg[option.size()] == '\0') {
    ++*index;
    *out_arg = argv[*index];
    return true;
  }
  if (arg[option.size()] == '=') {
    *out_arg = arg + option.size() + 1;
    return true;
  }
  // E.g, -j999
  if (option.size() == 2) {
    *out_arg = arg + option.size();
    return true;
  }
  return false;
}

static void ParseCommandLine(int argc, char* argv[],
                             vector<Symbol>* targets,
                             vector<StringPiece>* cl_vars) {
  // TODO: Decide the appropriate number based on the number of cores.
  g_num_jobs = 32;
  const char* num_jobs_str;

  for (int i = 1; i < argc; i++) {
    const char* arg = argv[i];
    if (!strcmp(arg, "-f")) {
      g_makefile = argv[++i];
    } else if (!strcmp(arg, "-c")) {
      g_is_syntax_check_only = true;
    } else if (!strcmp(arg, "-i")) {
      g_is_dry_run = true;
    } else if (!strcmp(arg, "--kati_stats")) {
      g_enable_stat_logs = true;
    } else if (!strcmp(arg, "--ninja")) {
      g_generate_ninja = true;
    } else if (!strcmp(arg, "--regen")) {
      // TODO: Make this default.
      g_regen = true;
    } else if (!strcmp(arg, "--detect_android_echo")) {
      g_detect_android_echo = true;
    } else if (!strcmp(arg, "--error_on_env_change")) {
      g_error_on_env_change = true;
    } else if (ParseCommandLineOptionWithArg(
        "-j", argv, &i, &num_jobs_str)) {
      g_num_jobs = strtol(num_jobs_str, NULL, 10);
      if (g_num_jobs <= 0) {
        ERROR("Invalid -j flag: %s", num_jobs_str);
      }
    } else if (ParseCommandLineOptionWithArg(
        "--ninja_suffix", argv, &i, &g_ninja_suffix)) {
    } else if (ParseCommandLineOptionWithArg(
        "--ninja_dir", argv, &i, &g_ninja_dir)) {
    } else if (!strcmp(arg, "--use_find_emulator")) {
      g_use_find_emulator = true;
    } else if (!strcmp(arg, "--gen_regen_rule")) {
      // TODO: Make this default once we have removed unnecessary
      // command line change from Android build.
      g_gen_regen_rule = true;
    } else if (ParseCommandLineOptionWithArg(
        "--goma_dir", argv, &i, &g_goma_dir)) {
    } else if (ParseCommandLineOptionWithArg(
        "--ignore_optional_include",
        argv, &i, &g_ignore_optional_include_pattern)) {
    } else if (arg[0] == '-') {
      ERROR("Unknown flag: %s", arg);
    } else {
      if (strchr(arg, '=')) {
        cl_vars->push_back(arg);
      } else {
        targets->push_back(Intern(arg));
      }
    }
  }
}

static void Init() {
  InitSymtab();
  InitFuncTable();
  InitDepNodePool();
  InitParser();

  if (g_makefile == NULL) {
    if (Exists("GNUmakefile")) {
      g_makefile = "GNUmakefile";
#if !defined(__APPLE__)
    } else if (Exists("makefile")) {
      g_makefile = "makefile";
#endif
    } else if (Exists("Makefile")) {
      g_makefile = "Makefile";
    } else {
      ERROR("*** No targets specified and no makefile found.");
    }
  }
}

static void Quit() {
  ReportAllStats();

  QuitParser();
  QuitDepNodePool();
  QuitFuncTable();
  QuitSymtab();
}

static void ReadBootstrapMakefile(const vector<Symbol>& targets,
                                  vector<AST*>* asts) {
  string bootstrap = (
      "CC:=cc\n"
#if defined(__APPLE__)
      "CXX:=c++\n"
#else
      "CXX:=g++\n"
#endif
      "AR:=ar\n"
      "MAKE:=kati\n"
      // Pretend to be GNU make 3.81, for compatibility.
      "MAKE_VERSION:=3.81\n"
      "SHELL:=/bin/sh\n"
      // TODO: Add more builtin vars.

      // http://www.gnu.org/software/make/manual/make.html#Catalogue-of-Rules
      // The document above is actually not correct. See default.c:
      // http://git.savannah.gnu.org/cgit/make.git/tree/default.c?id=4.1
      ".c.o:\n"
      "\t$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<\n"
      ".cc.o:\n"
      "\t$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<\n"
      // TODO: Add more builtin rules.
                      );
  bootstrap += StringPrintf("MAKECMDGOALS:=%s\n",
                            JoinSymbols(targets, " ").c_str());

  char cwd[PATH_MAX];
  if (!getcwd(cwd, PATH_MAX)) {
    fprintf(stderr, "getcwd failed\n");
    CHECK(false);
  }
  bootstrap += StringPrintf("CURDIR:=%s\n", cwd);
  Parse(Intern(bootstrap).str(), Loc("*bootstrap*", 0), asts);
}

static void SetVar(StringPiece l, VarOrigin origin, Vars* vars) {
  size_t found = l.find('=');
  CHECK(found != string::npos);
  Symbol lhs = Intern(l.substr(0, found));
  StringPiece rhs = l.substr(found + 1);
  vars->Assign(lhs,
               new RecursiveVar(NewLiteral(rhs.data()), origin, rhs.data()));
}

extern "C" char** environ;
static void FillDefaultVars(const vector<StringPiece>& cl_vars, Vars* vars) {
  for (char** p = environ; *p; p++) {
    SetVar(*p, VarOrigin::ENVIRONMENT, vars);
  }
  for (StringPiece l : cl_vars) {
    SetVar(l, VarOrigin::COMMAND_LINE, vars);
  }
}

static int Run(const vector<Symbol>& targets,
               const vector<StringPiece>& cl_vars,
               const string& orig_args) {
  if (g_generate_ninja && g_regen) {
    ScopedTimeReporter tr("regen check time");
    if (!NeedsRegen(g_ninja_suffix, g_ninja_dir)) {
      fprintf(stderr, "No need to regenerate ninja file\n");
      return 0;
    }
    ClearGlobCache();
  }

  double start_time = GetTime();

  MakefileCacheManager* cache_mgr = NewMakefileCacheManager();

  Vars* vars = new Vars();
  FillDefaultVars(cl_vars, vars);
  Evaluator* ev = new Evaluator(vars);

  vector<AST*> bootstrap_asts;
  ReadBootstrapMakefile(targets, &bootstrap_asts);
  ev->set_is_bootstrap(true);
  for (AST* ast : bootstrap_asts) {
    LOG("%s", ast->DebugString().c_str());
    ast->Eval(ev);
  }
  ev->set_is_bootstrap(false);

  vars->Assign(Intern("MAKEFILE_LIST"),
               new SimpleVar(make_shared<string>(
                   StringPrintf(" %s", g_makefile)), VarOrigin::FILE));

  {
    ScopedTimeReporter tr("eval time");
    Makefile* mk = cache_mgr->ReadMakefile(g_makefile);
    for (AST* ast : mk->asts()) {
      LOG("%s", ast->DebugString().c_str());
      ast->Eval(ev);
    }
  }

  vector<DepNode*> nodes;
  {
    ScopedTimeReporter tr("make dep time");
    MakeDep(ev, ev->rules(), ev->rule_vars(), targets, &nodes);
  }

  if (g_is_syntax_check_only)
    return 0;

  if (g_generate_ninja) {
    ScopedTimeReporter tr("generate ninja time");
    GenerateNinja(g_ninja_suffix, g_ninja_dir, nodes, ev, !targets.empty(),
                  orig_args, start_time);
    return 0;
  }

  for (const auto& p : ev->exports()) {
    const Symbol name = p.first;
    if (p.second) {
      Var* v = ev->LookupVar(name);
      shared_ptr<string> value = v->Eval(ev);
      LOG("setenv(%s, %s)", name.c_str(), value->c_str());
      setenv(name.c_str(), value->c_str(), 1);
    } else {
      LOG("unsetenv(%s)", name.c_str());
      unsetenv(name.c_str());
    }
  }

  {
    ScopedTimeReporter tr("exec time");
    Exec(nodes, ev);
  }

  for (AST* ast : bootstrap_asts)
    delete ast;
  delete ev;
  delete vars;
  delete cache_mgr;

  return 0;
}

int main(int argc, char* argv[]) {
  Init();
  string orig_args;
  for (int i = 0; i < argc; i++) {
    if (i)
      orig_args += ' ';
    orig_args += argv[i];
  }
  vector<Symbol> targets;
  vector<StringPiece> cl_vars;
  ParseCommandLine(argc, argv, &targets, &cl_vars);
  // This depends on command line flags.
  if (g_use_find_emulator)
    InitFindEmulator();
  int r = Run(targets, cl_vars, orig_args);
  Quit();
  return r;
}
<commit_msg>[C++] Automatically set -j based on the number of CPUs<commit_after>// Copyright 2015 Google Inc. All rights reserved
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// +build ignore

#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>

#include "ast.h"
#include "dep.h"
#include "eval.h"
#include "exec.h"
#include "file.h"
#include "file_cache.h"
#include "fileutil.h"
#include "find.h"
#include "flags.h"
#include "func.h"
#include "log.h"
#include "ninja.h"
#include "parser.h"
#include "stats.h"
#include "string_piece.h"
#include "stringprintf.h"
#include "strutil.h"
#include "symtab.h"
#include "timeutil.h"
#include "var.h"

static const char* g_makefile;
static bool g_is_syntax_check_only;
static bool g_generate_ninja;
static bool g_regen;
static const char* g_ninja_suffix;
static const char* g_ninja_dir;
static bool g_use_find_emulator;

static bool ParseCommandLineOptionWithArg(StringPiece option,
                                          char* argv[],
                                          int* index,
                                          const char** out_arg) {
  const char* arg = argv[*index];
  if (!HasPrefix(arg, option))
    return false;
  if (arg[option.size()] == '\0') {
    ++*index;
    *out_arg = argv[*index];
    return true;
  }
  if (arg[option.size()] == '=') {
    *out_arg = arg + option.size() + 1;
    return true;
  }
  // E.g, -j999
  if (option.size() == 2) {
    *out_arg = arg + option.size();
    return true;
  }
  return false;
}

static void ParseCommandLine(int argc, char* argv[],
                             vector<Symbol>* targets,
                             vector<StringPiece>* cl_vars) {
  g_num_jobs = sysconf(_SC_NPROCESSORS_ONLN);
  const char* num_jobs_str;

  for (int i = 1; i < argc; i++) {
    const char* arg = argv[i];
    if (!strcmp(arg, "-f")) {
      g_makefile = argv[++i];
    } else if (!strcmp(arg, "-c")) {
      g_is_syntax_check_only = true;
    } else if (!strcmp(arg, "-i")) {
      g_is_dry_run = true;
    } else if (!strcmp(arg, "--kati_stats")) {
      g_enable_stat_logs = true;
    } else if (!strcmp(arg, "--ninja")) {
      g_generate_ninja = true;
    } else if (!strcmp(arg, "--regen")) {
      // TODO: Make this default.
      g_regen = true;
    } else if (!strcmp(arg, "--detect_android_echo")) {
      g_detect_android_echo = true;
    } else if (!strcmp(arg, "--error_on_env_change")) {
      g_error_on_env_change = true;
    } else if (ParseCommandLineOptionWithArg(
        "-j", argv, &i, &num_jobs_str)) {
      g_num_jobs = strtol(num_jobs_str, NULL, 10);
      if (g_num_jobs <= 0) {
        ERROR("Invalid -j flag: %s", num_jobs_str);
      }
    } else if (ParseCommandLineOptionWithArg(
        "--ninja_suffix", argv, &i, &g_ninja_suffix)) {
    } else if (ParseCommandLineOptionWithArg(
        "--ninja_dir", argv, &i, &g_ninja_dir)) {
    } else if (!strcmp(arg, "--use_find_emulator")) {
      g_use_find_emulator = true;
    } else if (!strcmp(arg, "--gen_regen_rule")) {
      // TODO: Make this default once we have removed unnecessary
      // command line change from Android build.
      g_gen_regen_rule = true;
    } else if (ParseCommandLineOptionWithArg(
        "--goma_dir", argv, &i, &g_goma_dir)) {
    } else if (ParseCommandLineOptionWithArg(
        "--ignore_optional_include",
        argv, &i, &g_ignore_optional_include_pattern)) {
    } else if (arg[0] == '-') {
      ERROR("Unknown flag: %s", arg);
    } else {
      if (strchr(arg, '=')) {
        cl_vars->push_back(arg);
      } else {
        targets->push_back(Intern(arg));
      }
    }
  }
}

static void Init() {
  InitSymtab();
  InitFuncTable();
  InitDepNodePool();
  InitParser();

  if (g_makefile == NULL) {
    if (Exists("GNUmakefile")) {
      g_makefile = "GNUmakefile";
#if !defined(__APPLE__)
    } else if (Exists("makefile")) {
      g_makefile = "makefile";
#endif
    } else if (Exists("Makefile")) {
      g_makefile = "Makefile";
    } else {
      ERROR("*** No targets specified and no makefile found.");
    }
  }
}

static void Quit() {
  ReportAllStats();

  QuitParser();
  QuitDepNodePool();
  QuitFuncTable();
  QuitSymtab();
}

static void ReadBootstrapMakefile(const vector<Symbol>& targets,
                                  vector<AST*>* asts) {
  string bootstrap = (
      "CC:=cc\n"
#if defined(__APPLE__)
      "CXX:=c++\n"
#else
      "CXX:=g++\n"
#endif
      "AR:=ar\n"
      "MAKE:=kati\n"
      // Pretend to be GNU make 3.81, for compatibility.
      "MAKE_VERSION:=3.81\n"
      "SHELL:=/bin/sh\n"
      // TODO: Add more builtin vars.

      // http://www.gnu.org/software/make/manual/make.html#Catalogue-of-Rules
      // The document above is actually not correct. See default.c:
      // http://git.savannah.gnu.org/cgit/make.git/tree/default.c?id=4.1
      ".c.o:\n"
      "\t$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<\n"
      ".cc.o:\n"
      "\t$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<\n"
      // TODO: Add more builtin rules.
                      );
  bootstrap += StringPrintf("MAKECMDGOALS:=%s\n",
                            JoinSymbols(targets, " ").c_str());

  char cwd[PATH_MAX];
  if (!getcwd(cwd, PATH_MAX)) {
    fprintf(stderr, "getcwd failed\n");
    CHECK(false);
  }
  bootstrap += StringPrintf("CURDIR:=%s\n", cwd);
  Parse(Intern(bootstrap).str(), Loc("*bootstrap*", 0), asts);
}

static void SetVar(StringPiece l, VarOrigin origin, Vars* vars) {
  size_t found = l.find('=');
  CHECK(found != string::npos);
  Symbol lhs = Intern(l.substr(0, found));
  StringPiece rhs = l.substr(found + 1);
  vars->Assign(lhs,
               new RecursiveVar(NewLiteral(rhs.data()), origin, rhs.data()));
}

extern "C" char** environ;
static void FillDefaultVars(const vector<StringPiece>& cl_vars, Vars* vars) {
  for (char** p = environ; *p; p++) {
    SetVar(*p, VarOrigin::ENVIRONMENT, vars);
  }
  for (StringPiece l : cl_vars) {
    SetVar(l, VarOrigin::COMMAND_LINE, vars);
  }
}

static int Run(const vector<Symbol>& targets,
               const vector<StringPiece>& cl_vars,
               const string& orig_args) {
  if (g_generate_ninja && g_regen) {
    ScopedTimeReporter tr("regen check time");
    if (!NeedsRegen(g_ninja_suffix, g_ninja_dir)) {
      fprintf(stderr, "No need to regenerate ninja file\n");
      return 0;
    }
    ClearGlobCache();
  }

  double start_time = GetTime();

  MakefileCacheManager* cache_mgr = NewMakefileCacheManager();

  Vars* vars = new Vars();
  FillDefaultVars(cl_vars, vars);
  Evaluator* ev = new Evaluator(vars);

  vector<AST*> bootstrap_asts;
  ReadBootstrapMakefile(targets, &bootstrap_asts);
  ev->set_is_bootstrap(true);
  for (AST* ast : bootstrap_asts) {
    LOG("%s", ast->DebugString().c_str());
    ast->Eval(ev);
  }
  ev->set_is_bootstrap(false);

  vars->Assign(Intern("MAKEFILE_LIST"),
               new SimpleVar(make_shared<string>(
                   StringPrintf(" %s", g_makefile)), VarOrigin::FILE));

  {
    ScopedTimeReporter tr("eval time");
    Makefile* mk = cache_mgr->ReadMakefile(g_makefile);
    for (AST* ast : mk->asts()) {
      LOG("%s", ast->DebugString().c_str());
      ast->Eval(ev);
    }
  }

  vector<DepNode*> nodes;
  {
    ScopedTimeReporter tr("make dep time");
    MakeDep(ev, ev->rules(), ev->rule_vars(), targets, &nodes);
  }

  if (g_is_syntax_check_only)
    return 0;

  if (g_generate_ninja) {
    ScopedTimeReporter tr("generate ninja time");
    GenerateNinja(g_ninja_suffix, g_ninja_dir, nodes, ev, !targets.empty(),
                  orig_args, start_time);
    return 0;
  }

  for (const auto& p : ev->exports()) {
    const Symbol name = p.first;
    if (p.second) {
      Var* v = ev->LookupVar(name);
      shared_ptr<string> value = v->Eval(ev);
      LOG("setenv(%s, %s)", name.c_str(), value->c_str());
      setenv(name.c_str(), value->c_str(), 1);
    } else {
      LOG("unsetenv(%s)", name.c_str());
      unsetenv(name.c_str());
    }
  }

  {
    ScopedTimeReporter tr("exec time");
    Exec(nodes, ev);
  }

  for (AST* ast : bootstrap_asts)
    delete ast;
  delete ev;
  delete vars;
  delete cache_mgr;

  return 0;
}

int main(int argc, char* argv[]) {
  Init();
  string orig_args;
  for (int i = 0; i < argc; i++) {
    if (i)
      orig_args += ' ';
    orig_args += argv[i];
  }
  vector<Symbol> targets;
  vector<StringPiece> cl_vars;
  ParseCommandLine(argc, argv, &targets, &cl_vars);
  // This depends on command line flags.
  if (g_use_find_emulator)
    InitFindEmulator();
  int r = Run(targets, cl_vars, orig_args);
  Quit();
  return r;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 David Chisnall
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
#include <iostream>
#include <ctype.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/resource.h>
#include <libgen.h>
#include <time.h>
#include <unistd.h>
#include "parser.hh"
#include "ast.hh"

static int enableTiming = 0;

static void logTimeSince(clock_t c1, const char *msg)
{
	if (!enableTiming) { return; }
	clock_t c2 = clock();
	struct rusage r;
	getrusage(RUSAGE_SELF, &r);
	fprintf(stderr, "%s took %f seconds.	Peak used %ldKB.\n", msg,
		(static_cast<double>(c2) - static_cast<double>(c1)) / static_cast<double>(CLOCKS_PER_SEC), r.ru_maxrss);
}

int main(int argc, char **argv)
{
	std::string path = dirname(argv[0]);
	int iterations = 1;
	int useJIT = 0;
	int optimiseLevel = 0;
	int gridSize = 5;
	int maxValue = 1;
	clock_t c1;
	int c;
	while ((c = getopt(argc, argv, "ji:tO:x:m:")) != -1)
	{
		switch (c)
		{
			default:
				break;
			case 'j':
				useJIT = 1;
				break;
			case 'x':
				gridSize = strtol(optarg, 0, 10);
				break;
			case 'm':
				maxValue = strtol(optarg, 0, 10);
				break;
			case 'i':
				iterations = strtol(optarg, 0, 10);
				break;
			case 't':
				enableTiming = 1;
				break;
			case 'O':
				optimiseLevel = strtol(optarg, 0, 10);
		}
	}
	argc -= optind;
	if (argc < 1)
	{
		fprintf(stderr, "usage: %s -jt -i {iterations} -O {optimisation level} -x {grid size} -m {max initial value} {file name}\n", argv[0]);
		return EXIT_FAILURE;
	}
	if (gridSize < 1 || gridSize >= 1<<15)
	{
		fprintf(stderr, "Grid size must be between 1 and 2^15\n");
		return EXIT_FAILURE;
	}
	argv += optind;

	// Do the parsing
	Parser::CellAtomParser p;
	pegmatite::AsciiFileInput input(open(argv[0], O_RDONLY));
	std::unique_ptr<AST::StatementList> ast = 0;
	c1 = clock();
	pegmatite::ErrorReporter err =
		[](const pegmatite::InputRange& r, const std::string& msg) {
		std::cout << "error: " << msg << std::endl;
		std::cout << "line " << r.start.line
		          << ", col " << r.start.col << std::endl;
	};
	if (!p.parse(input, p.g.statements, p.g.ignored, err, ast))
	{
		return EXIT_FAILURE;
	}
	logTimeSince(c1, "Parsing program");
	assert(ast);

#ifdef DUMP_AST
	for (uintptr_t i=0 ; i<result->count ; i++)
	{
		printAST(result->list[i]);
		putchar('\n');
	}
#endif
#ifdef STATIC_TESTING_GRID
	int16_t oldgrid[] = {
		 0,0,0,0,0,
		 0,0,0,0,0,
		 0,1,1,1,0,
		 0,0,0,0,0,
		 0,0,0,0,0
	};
	int16_t newgrid[25];
	gridSize = 5;
	int16_t *g1 = oldgrid;
	int16_t *g2 = newgrid;
#else
	int16_t *g1 = reinterpret_cast<int16_t*>(malloc(sizeof(int16_t) * gridSize * gridSize));
	int16_t *g2 = reinterpret_cast<int16_t*>(malloc(sizeof(int16_t) * gridSize * gridSize));
	//int16_t *g2 = new int16_t[gridSize * gridSize];
	c1 = clock();
	for (int i=0 ; i<(gridSize*gridSize) ; i++)
	{
		g1[i] = random() % (maxValue + 1);
	}
	logTimeSince(c1, "Generating random grid");
#endif
	int i=0;
	if (useJIT)
	{
		c1 = clock();
		Compiler::automaton ca = Compiler::compile(ast.get(), optimiseLevel, path);
		logTimeSince(c1, "Compiling");
		c1 = clock();
		for (int i=0 ; i<iterations ; i++)
		{
			ca(g1, g2, gridSize, gridSize);
			std::swap(g1, g2);
		}
		logTimeSince(c1, "Running compiled version");
	}
	else
	{
		c1 = clock();
		for (int i=0 ; i<iterations ; i++)
		{
			Interpreter::runOneStep(g1, g2, gridSize, gridSize, ast.get());
			std::swap(g1, g2);
		}
		logTimeSince(c1, "Interpreting");
	}
	for (int x=0 ; x<gridSize ; x++)
	{
		for (int y=0 ; y<gridSize ; y++)
		{
			printf("%d ", g1[i++]);
		}
		putchar('\n');
	}
	return 0;
}
<commit_msg>Make a boolean value into a bool.<commit_after>/*
 * Copyright (c) 2014 David Chisnall
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
#include <iostream>
#include <ctype.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/resource.h>
#include <libgen.h>
#include <time.h>
#include <unistd.h>
#include "parser.hh"
#include "ast.hh"

static int enableTiming = 0;

static void logTimeSince(clock_t c1, const char *msg)
{
	if (!enableTiming) { return; }
	clock_t c2 = clock();
	struct rusage r;
	getrusage(RUSAGE_SELF, &r);
	fprintf(stderr, "%s took %f seconds.	Peak used %ldKB.\n", msg,
		(static_cast<double>(c2) - static_cast<double>(c1)) / static_cast<double>(CLOCKS_PER_SEC), r.ru_maxrss);
}

int main(int argc, char **argv)
{
	std::string path = dirname(argv[0]);
	int iterations = 1;
	bool useJIT = false;
	int optimiseLevel = 0;
	int gridSize = 5;
	int maxValue = 1;
	clock_t c1;
	int c;
	while ((c = getopt(argc, argv, "ji:tO:x:m:")) != -1)
	{
		switch (c)
		{
			default:
				break;
			case 'j':
				useJIT = 1;
				break;
			case 'x':
				gridSize = strtol(optarg, 0, 10);
				break;
			case 'm':
				maxValue = strtol(optarg, 0, 10);
				break;
			case 'i':
				iterations = strtol(optarg, 0, 10);
				break;
			case 't':
				enableTiming = true;
				break;
			case 'O':
				optimiseLevel = strtol(optarg, 0, 10);
		}
	}
	argc -= optind;
	if (argc < 1)
	{
		fprintf(stderr, "usage: %s -jt -i {iterations} -O {optimisation level} -x {grid size} -m {max initial value} {file name}\n", argv[0]);
		return EXIT_FAILURE;
	}
	if (gridSize < 1 || gridSize >= 1<<15)
	{
		fprintf(stderr, "Grid size must be between 1 and 2^15\n");
		return EXIT_FAILURE;
	}
	argv += optind;

	// Do the parsing
	Parser::CellAtomParser p;
	pegmatite::AsciiFileInput input(open(argv[0], O_RDONLY));
	std::unique_ptr<AST::StatementList> ast = 0;
	c1 = clock();
	pegmatite::ErrorReporter err =
		[](const pegmatite::InputRange& r, const std::string& msg) {
		std::cout << "error: " << msg << std::endl;
		std::cout << "line " << r.start.line
		          << ", col " << r.start.col << std::endl;
	};
	if (!p.parse(input, p.g.statements, p.g.ignored, err, ast))
	{
		return EXIT_FAILURE;
	}
	logTimeSince(c1, "Parsing program");
	assert(ast);

#ifdef DUMP_AST
	for (uintptr_t i=0 ; i<result->count ; i++)
	{
		printAST(result->list[i]);
		putchar('\n');
	}
#endif
#ifdef STATIC_TESTING_GRID
	int16_t oldgrid[] = {
		 0,0,0,0,0,
		 0,0,0,0,0,
		 0,1,1,1,0,
		 0,0,0,0,0,
		 0,0,0,0,0
	};
	int16_t newgrid[25];
	gridSize = 5;
	int16_t *g1 = oldgrid;
	int16_t *g2 = newgrid;
#else
	int16_t *g1 = reinterpret_cast<int16_t*>(malloc(sizeof(int16_t) * gridSize * gridSize));
	int16_t *g2 = reinterpret_cast<int16_t*>(malloc(sizeof(int16_t) * gridSize * gridSize));
	//int16_t *g2 = new int16_t[gridSize * gridSize];
	c1 = clock();
	for (int i=0 ; i<(gridSize*gridSize) ; i++)
	{
		g1[i] = random() % (maxValue + 1);
	}
	logTimeSince(c1, "Generating random grid");
#endif
	int i=0;
	if (useJIT)
	{
		c1 = clock();
		Compiler::automaton ca = Compiler::compile(ast.get(), optimiseLevel, path);
		logTimeSince(c1, "Compiling");
		c1 = clock();
		for (int i=0 ; i<iterations ; i++)
		{
			ca(g1, g2, gridSize, gridSize);
			std::swap(g1, g2);
		}
		logTimeSince(c1, "Running compiled version");
	}
	else
	{
		c1 = clock();
		for (int i=0 ; i<iterations ; i++)
		{
			Interpreter::runOneStep(g1, g2, gridSize, gridSize, ast.get());
			std::swap(g1, g2);
		}
		logTimeSince(c1, "Interpreting");
	}
	for (int x=0 ; x<gridSize ; x++)
	{
		for (int y=0 ; y<gridSize ; y++)
		{
			printf("%d ", g1[i++]);
		}
		putchar('\n');
	}
	return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium OS 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 <cmath>
#include <cstdlib>
#include <ctime>

extern "C" {
#include <X11/Xlib.h>
}

#include <gflags/gflags.h>

#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/scoped_ptr.h"
#include "base/string_util.h"
#include "window_manager/callback.h"
#include "window_manager/event_loop.h"
#include "window_manager/profiler.h"
#include "window_manager/real_compositor.h"
#if defined(COMPOSITOR_OPENGL)
#include "window_manager/real_gl_interface.h"
#elif defined(COMPOSITOR_OPENGLES)
#include "window_manager/gles/real_gles2_interface.h"
#endif
#include "window_manager/real_x_connection.h"
#include "window_manager/util.h"
#include "window_manager/window_manager.h"

DEFINE_string(display, "",
              "X Display to connect to (overrides DISPLAY env var).");
DEFINE_bool(logtostderr, false,
            "Log to stderr (see --logged_{in,out}_log_dir otherwise)");
DEFINE_string(profile_dir, "./profile",
              "Directory where profiles should be written; created if it "
              "doesn't exist.");
DEFINE_int32(profile_max_samples, 200,
             "Maximum number of samples (buffer size) for profiler.");
DEFINE_bool(start_profiler, false,
            "Start profiler at window manager startup.");
DEFINE_int32(pause_at_start, 0,
             "Specify this to pause for N seconds at startup.");

using std::string;
using window_manager::EventLoop;
using window_manager::RealCompositor;
#if defined(COMPOSITOR_OPENGL)
using window_manager::RealGLInterface;
#elif defined(COMPOSITOR_OPENGLES)
using window_manager::RealGles2Interface;
#else
#error COMPOSITOR_OPENGL or COMPOSITOR_OPENGLES must be defined
#endif
using window_manager::RealXConnection;
using window_manager::WindowManager;
using window_manager::util::GetTimeAsString;
using window_manager::util::SetUpLogSymlink;

// This should be adjusted according to number of PROFILER_MARKER_*
static const int kMaxNumProfilerSymbols = 100;

// Handler called by Chrome logging code on failed asserts.
static void HandleLogAssert(const string& str) {
  abort();
}

int main(int argc, char** argv) {
  base::AtExitManager exit_manager;  // needed by base::Singleton

  google::ParseCommandLineFlags(&argc, &argv, true);
  if (!FLAGS_display.empty())
    setenv("DISPLAY", FLAGS_display.c_str(), 1);

  CommandLine::Init(argc, argv);
  if (FLAGS_pause_at_start > 0)
    sleep(FLAGS_pause_at_start);

  // Just log to stderr initially; WindowManager will re-initialize to
  // switch to a file once we know whether we're logged in or not if
  // --logtostderr is false.
  logging::InitLogging(NULL,
                       logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG,
                       logging::DONT_LOCK_LOG_FILE,
                       logging::APPEND_TO_OLD_LOG_FILE);

  // Chrome's logging code uses int3 to send SIGTRAP in response to failed
  // asserts, but Breakpad only installs signal handlers for SEGV, ABRT,
  // FPE, ILL, and BUS.  Use our own function to send ABRT instead.
  logging::SetLogAssertHandler(HandleLogAssert);

#if defined(PROFILE_BUILD)
  const string profile_basename = StringPrintf(
      "prof_%s.%s", WindowManager::GetWmName(),
      GetTimeAsString(::time(NULL)).c_str());

  if (!file_util::CreateDirectory(FilePath(FLAGS_profile_dir))) {
    LOG(ERROR) << "Unable to create profiling directory " << FLAGS_profile_dir;
  } else {
    SetUpLogSymlink(StringPrintf("%s/prof_%s.LATEST",
                                 FLAGS_profile_dir.c_str(),
                                 WindowManager::GetWmName()),
                    profile_basename);
  }

  const string profile_path = FLAGS_profile_dir + "/" + profile_basename;
  Singleton<window_manager::Profiler>()->Start(
      new window_manager::ProfilerWriter(FilePath(profile_path)),
      kMaxNumProfilerSymbols, FLAGS_profile_max_samples);

  Singleton<window_manager::DynamicMarker>()->set_profiler(
      Singleton<window_manager::Profiler>::get());

  if (!FLAGS_start_profiler) {
    Singleton<window_manager::Profiler>()->Pause();
  }
#endif

  const char* display_name = getenv("DISPLAY");
  Display* display = XOpenDisplay(display_name);
  CHECK(display) << "Unable to open "
                 << (display_name ? display_name : "default display");

  RealXConnection xconn(display);
  EventLoop event_loop;
#if defined(COMPOSITOR_OPENGL)
  RealGLInterface gl_interface(&xconn);
#elif defined(COMPOSITOR_OPENGLES)
  RealGles2Interface gl_interface(&xconn);
#endif
  RealCompositor compositor(&event_loop, &xconn, &gl_interface);

  WindowManager wm(&event_loop, &xconn, &compositor);
  wm.set_initialize_logging(!FLAGS_logtostderr);
  wm.Init();

  // TODO: Need to also use XAddConnectionWatch()?
  const int x11_fd = xconn.GetConnectionFileDescriptor();
  LOG(INFO) << "X11 connection is on fd " << x11_fd;
  event_loop.AddFileDescriptor(
      x11_fd, NewPermanentCallback(&wm, &WindowManager::ProcessPendingEvents));
  event_loop.AddPrePollCallback(
      NewPermanentCallback(&wm, &WindowManager::ProcessPendingEvents));

  event_loop.Run();
  return 0;
}
<commit_msg>wm: exit(1) instead of raising SIGABRT when X dies.<commit_after>// Copyright (c) 2010 The Chromium OS 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 <cmath>
#include <cstdlib>
#include <ctime>

extern "C" {
#include <X11/Xlib.h>
}

#include <gflags/gflags.h>

#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/scoped_ptr.h"
#include "base/string_util.h"
#include "window_manager/callback.h"
#include "window_manager/event_loop.h"
#include "window_manager/profiler.h"
#include "window_manager/real_compositor.h"
#if defined(COMPOSITOR_OPENGL)
#include "window_manager/real_gl_interface.h"
#elif defined(COMPOSITOR_OPENGLES)
#include "window_manager/gles/real_gles2_interface.h"
#endif
#include "window_manager/real_x_connection.h"
#include "window_manager/util.h"
#include "window_manager/window_manager.h"

DEFINE_string(display, "",
              "X Display to connect to (overrides DISPLAY env var).");
DEFINE_bool(logtostderr, false,
            "Log to stderr (see --logged_{in,out}_log_dir otherwise)");
DEFINE_string(profile_dir, "./profile",
              "Directory where profiles should be written; created if it "
              "doesn't exist.");
DEFINE_int32(profile_max_samples, 200,
             "Maximum number of samples (buffer size) for profiler.");
DEFINE_bool(start_profiler, false,
            "Start profiler at window manager startup.");
DEFINE_int32(pause_at_start, 0,
             "Specify this to pause for N seconds at startup.");

using std::string;
using window_manager::EventLoop;
using window_manager::RealCompositor;
#if defined(COMPOSITOR_OPENGL)
using window_manager::RealGLInterface;
#elif defined(COMPOSITOR_OPENGLES)
using window_manager::RealGles2Interface;
#else
#error COMPOSITOR_OPENGL or COMPOSITOR_OPENGLES must be defined
#endif
using window_manager::RealXConnection;
using window_manager::WindowManager;
using window_manager::util::GetTimeAsString;
using window_manager::util::SetUpLogSymlink;

// This should be adjusted according to number of PROFILER_MARKER_*
static const int kMaxNumProfilerSymbols = 100;

// Handler called by Chrome logging code on failed asserts.
static void HandleLogAssert(const string& str) {
  abort();
}

// Handler called in response to Xlib I/O errors.  We install this so we won't
// generate a window manager crash dump whenever the X server crashes.
static int HandleXIOError(Display* display) {
  LOG(ERROR) << "Got X I/O error (probably lost connection to server); exiting";
  exit(EXIT_FAILURE);
}

int main(int argc, char** argv) {
  base::AtExitManager exit_manager;  // needed by base::Singleton

  google::ParseCommandLineFlags(&argc, &argv, true);
  if (!FLAGS_display.empty())
    setenv("DISPLAY", FLAGS_display.c_str(), 1);

  CommandLine::Init(argc, argv);
  if (FLAGS_pause_at_start > 0)
    sleep(FLAGS_pause_at_start);

  // Just log to stderr initially; WindowManager will re-initialize to
  // switch to a file once we know whether we're logged in or not if
  // --logtostderr is false.
  logging::InitLogging(NULL,
                       logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG,
                       logging::DONT_LOCK_LOG_FILE,
                       logging::APPEND_TO_OLD_LOG_FILE);

  // Chrome's logging code uses int3 to send SIGTRAP in response to failed
  // asserts, but Breakpad only installs signal handlers for SEGV, ABRT,
  // FPE, ILL, and BUS.  Use our own function to send ABRT instead.
  logging::SetLogAssertHandler(HandleLogAssert);

#if defined(PROFILE_BUILD)
  const string profile_basename = StringPrintf(
      "prof_%s.%s", WindowManager::GetWmName(),
      GetTimeAsString(::time(NULL)).c_str());

  if (!file_util::CreateDirectory(FilePath(FLAGS_profile_dir))) {
    LOG(ERROR) << "Unable to create profiling directory " << FLAGS_profile_dir;
  } else {
    SetUpLogSymlink(StringPrintf("%s/prof_%s.LATEST",
                                 FLAGS_profile_dir.c_str(),
                                 WindowManager::GetWmName()),
                    profile_basename);
  }

  const string profile_path = FLAGS_profile_dir + "/" + profile_basename;
  Singleton<window_manager::Profiler>()->Start(
      new window_manager::ProfilerWriter(FilePath(profile_path)),
      kMaxNumProfilerSymbols, FLAGS_profile_max_samples);

  Singleton<window_manager::DynamicMarker>()->set_profiler(
      Singleton<window_manager::Profiler>::get());

  if (!FLAGS_start_profiler) {
    Singleton<window_manager::Profiler>()->Pause();
  }
#endif

  const char* display_name = getenv("DISPLAY");
  Display* display = XOpenDisplay(display_name);
  if (!display) {
    LOG(ERROR) << "Unable to open "
               << (display_name ? display_name : "default display");
    exit(EXIT_FAILURE);
  }
  XSetIOErrorHandler(HandleXIOError);

  RealXConnection xconn(display);
  EventLoop event_loop;
#if defined(COMPOSITOR_OPENGL)
  RealGLInterface gl_interface(&xconn);
#elif defined(COMPOSITOR_OPENGLES)
  RealGles2Interface gl_interface(&xconn);
#endif
  RealCompositor compositor(&event_loop, &xconn, &gl_interface);

  WindowManager wm(&event_loop, &xconn, &compositor);
  wm.set_initialize_logging(!FLAGS_logtostderr);
  wm.Init();

  // TODO: Need to also use XAddConnectionWatch()?
  const int x11_fd = xconn.GetConnectionFileDescriptor();
  LOG(INFO) << "X11 connection is on fd " << x11_fd;
  event_loop.AddFileDescriptor(
      x11_fd, NewPermanentCallback(&wm, &WindowManager::ProcessPendingEvents));
  event_loop.AddPrePollCallback(
      NewPermanentCallback(&wm, &WindowManager::ProcessPendingEvents));

  event_loop.Run();
  return 0;
}
<|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/chromeos/login/existing_user_controller.h"

#include <algorithm>
#include <functional>
#include <map>

#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/message_loop.h"
#include "base/stl_util-inl.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/cros/login_library.h"
#include "chrome/browser/chromeos/cros/network_library.h"
#include "chrome/browser/chromeos/login/authenticator.h"
#include "chrome/browser/chromeos/login/background_view.h"
#include "chrome/browser/chromeos/login/helper.h"
#include "chrome/browser/chromeos/login/login_utils.h"
#include "chrome/browser/chromeos/login/message_bubble.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/browser/chromeos/wm_ipc.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/profile_manager.h"
#include "grit/theme_resources.h"
#include "views/screen.h"
#include "views/widget/widget.h"
#include "views/widget/widget_gtk.h"
#include "views/window/window.h"

namespace chromeos {

namespace {

// Max number of users we'll show. The true max is the min of this and the
// number of windows that fit on the screen.
const size_t kMaxUsers = 6;

// Used to indicate no user has been selected.
const size_t kNotSelected = -1;

// ClientLogin response parameters.
const char kError[] = "Error=";
const char kCaptchaError[] = "CaptchaRequired";
const char kCaptchaUrlParam[] = "CaptchaUrl=";
const char kCaptchaTokenParam[] = "CaptchaToken=";
const char kParamSuffix[] = "\n";

// URL prefix for CAPTCHA image.
const char kCaptchaUrlPrefix[] = "http://www.google.com/accounts/";

// Checks if display names are unique. If there are duplicates, enables
// tooltips with full emails to let users distinguish their accounts.
// Otherwise, disables the tooltips.
void EnableTooltipsIfNeeded(const std::vector<UserController*>& controllers) {
  std::map<std::string, int> visible_display_names;
  for (size_t i = 0; i + 1 < controllers.size(); ++i) {
    const std::string& display_name =
        controllers[i]->user().GetDisplayName();
    ++visible_display_names[display_name];
  }
  for (size_t i = 0; i + 1 < controllers.size(); ++i) {
    const std::string& display_name =
        controllers[i]->user().GetDisplayName();
    bool show_tooltip = visible_display_names[display_name] > 1;
    controllers[i]->EnableNameTooltip(show_tooltip);
  }
}

}  // namespace

ExistingUserController*
  ExistingUserController::delete_scheduled_instance_ = NULL;

ExistingUserController::ExistingUserController(
    const std::vector<UserManager::User>& users,
    const gfx::Rect& background_bounds)
    : background_bounds_(background_bounds),
      background_window_(NULL),
      background_view_(NULL),
      selected_view_index_(kNotSelected),
      bubble_(NULL) {
  if (delete_scheduled_instance_)
    delete_scheduled_instance_->Delete();

  // Caclulate the max number of users from available screen size.
  size_t max_users = kMaxUsers;
  int screen_width = background_bounds.width();
  if (screen_width > 0) {
    max_users = std::max(static_cast<size_t>(2), std::min(kMaxUsers,
        static_cast<size_t>((screen_width - login::kUserImageSize)
                            / (UserController::kUnselectedSize +
                               UserController::kPadding))));
  }

  size_t visible_users_count = std::min(users.size(), max_users - 1);
  for (size_t i = 0; i < visible_users_count; ++i)
    controllers_.push_back(new UserController(this, users[i]));

  // Add the view representing the guest user last.
  controllers_.push_back(new UserController(this));
}

void ExistingUserController::Init() {
  if (!background_window_) {
    background_window_ = BackgroundView::CreateWindowContainingView(
        background_bounds_,
        &background_view_);
    background_window_->Show();
  }
  for (size_t i = 0; i < controllers_.size(); ++i) {
    (controllers_[i])->Init(static_cast<int>(i),
                            static_cast<int>(controllers_.size()));
  }

  EnableTooltipsIfNeeded(controllers_);

  WmMessageListener::instance()->AddObserver(this);

  if (CrosLibrary::Get()->EnsureLoaded())
    CrosLibrary::Get()->GetLoginLibrary()->EmitLoginPromptReady();
}

void ExistingUserController::OwnBackground(
    views::Widget* background_widget,
    chromeos::BackgroundView* background_view) {
  DCHECK(!background_window_);
  background_window_ = background_widget;
  background_view_ = background_view;
}

ExistingUserController::~ExistingUserController() {
  ClearErrors();

  if (background_window_)
    background_window_->Close();

  WmMessageListener::instance()->RemoveObserver(this);

  STLDeleteElements(&controllers_);
}

void ExistingUserController::Delete() {
  delete_scheduled_instance_ = NULL;
  delete this;
}

void ExistingUserController::ProcessWmMessage(const WmIpc::Message& message,
                                              GdkWindow* window) {
  if (message.type() != WM_IPC_MESSAGE_CHROME_CREATE_GUEST_WINDOW)
    return;

  ActivateWizard(std::string());
}

void ExistingUserController::SendSetLoginState(bool is_enabled) {
  WmIpc::Message message(WM_IPC_MESSAGE_WM_SET_LOGIN_STATE);
  message.set_param(0, is_enabled);
  WmIpc::instance()->SendMessage(message);
}

void ExistingUserController::Login(UserController* source,
                                   const string16& password) {
  std::vector<UserController*>::const_iterator i =
      std::find(controllers_.begin(), controllers_.end(), source);
  DCHECK(i != controllers_.end());
  selected_view_index_ = i - controllers_.begin();

  authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
  Profile* profile = g_browser_process->profile_manager()->GetDefaultProfile();
  ChromeThread::PostTask(
      ChromeThread::UI, FROM_HERE,
      NewRunnableMethod(authenticator_.get(),
                        &Authenticator::AuthenticateToLogin,
                        profile,
                        controllers_[selected_view_index_]->user().email(),
                        UTF16ToUTF8(password),
                        login_token_,
                        login_captcha_));

  // Disable clicking on other windows.
  SendSetLoginState(false);
}

void ExistingUserController::LoginOffTheRecord() {
  authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
  ChromeThread::PostTask(
      ChromeThread::UI, FROM_HERE,
      NewRunnableMethod(authenticator_.get(),
                        &Authenticator::LoginOffTheRecord));

  // Disable clicking on other windows.
  SendSetLoginState(false);
}

void ExistingUserController::ClearErrors() {
  // bubble_ will be set to NULL in callback.
  if (bubble_)
    bubble_->Close();
}

void ExistingUserController::OnUserSelected(UserController* source) {
  std::vector<UserController*>::const_iterator i =
      std::find(controllers_.begin(), controllers_.end(), source);
  DCHECK(i != controllers_.end());
  size_t new_selected_index = i - controllers_.begin();
  if (new_selected_index != selected_view_index_ &&
      selected_view_index_ != kNotSelected) {
    controllers_[selected_view_index_]->ClearAndEnablePassword();
    ClearCaptchaState();
  }
  selected_view_index_ = new_selected_index;
}

void ExistingUserController::ActivateWizard(const std::string& screen_name) {
  // WizardController takes care of deleting itself when done.
  WizardController* controller = new WizardController();
  controller->Init(screen_name, background_bounds_);
  controller->Show();

  // Give the background window to the controller.
  controller->OwnBackground(background_window_, background_view_);
  background_window_ = NULL;

  // And schedule us for deletion. We delay for a second as the window manager
  // is doing an animation with our windows.
  DCHECK(!delete_scheduled_instance_);
  delete_scheduled_instance_ = this;
  delete_timer_.Start(base::TimeDelta::FromSeconds(1), this,
                      &ExistingUserController::Delete);
}

void ExistingUserController::RemoveUser(UserController* source) {
  ClearErrors();

  UserManager::Get()->RemoveUser(source->user().email());

  // We need to unmap entry windows, the windows will be unmapped in destructor.
  controllers_.erase(controllers_.begin() + source->user_index());
  delete source;

  EnableTooltipsIfNeeded(controllers_);
  int new_size = static_cast<int>(controllers_.size());
  for (int i = 0; i < new_size; ++i)
    controllers_[i]->UpdateUserCount(i, new_size);
}

void ExistingUserController::SelectUser(int index) {
  if (index >= 0 && index < static_cast<int>(controllers_.size()) &&
      index != static_cast<int>(selected_view_index_)) {
    WmIpc::Message message(WM_IPC_MESSAGE_WM_SELECT_LOGIN_USER);
    message.set_param(0, index);
    WmIpc::instance()->SendMessage(message);
  }
}

void ExistingUserController::OnLoginFailure(const std::string& error) {
  LOG(INFO) << "OnLoginFailure";
  ClearCaptchaState();

  // Check networking after trying to login in case user is
  // cached locally or the local admin account.
  NetworkLibrary* network = CrosLibrary::Get()->GetNetworkLibrary();
  if (!network || !CrosLibrary::Get()->EnsureLoaded()) {
    ShowError(IDS_LOGIN_ERROR_NO_NETWORK_LIBRARY, error);
  } else if (!network->Connected()) {
    ShowError(IDS_LOGIN_ERROR_OFFLINE_FAILED_NETWORK_NOT_CONNECTED, error);
  } else {
    std::string error_code = LoginUtils::ExtractClientLoginParam(error,
                                                                 kError,
                                                                 kParamSuffix);
    std::string captcha_url;
    if (error_code == kCaptchaError)
      captcha_url = LoginUtils::ExtractClientLoginParam(error,
                                                        kCaptchaUrlParam,
                                                        kParamSuffix);
    if (captcha_url.empty()) {
      ShowError(IDS_LOGIN_ERROR_AUTHENTICATING, error);
    } else {
      // Save token for next login retry.
      login_token_ = LoginUtils::ExtractClientLoginParam(error,
                                                         kCaptchaTokenParam,
                                                         kParamSuffix);
      gfx::NativeWindow parent = GTK_WINDOW(
          static_cast<views::WidgetGtk*>(background_window_)->GetNativeView());
      CaptchaView* view =
          new CaptchaView(GURL(kCaptchaUrlPrefix + captcha_url));
      view->set_delegate(this);
      views::Window* window = views::Window::CreateChromeWindow(parent,
                                                                gfx::Rect(),
                                                                view);
      window->SetIsAlwaysOnTop(true);
      window->Show();
    }
  }

  controllers_[selected_view_index_]->ClearAndEnablePassword();

  // Reenable clicking on other windows.
  SendSetLoginState(true);
}

void ExistingUserController::AppendStartUrlToCmdline() {
  if (start_url_.is_valid()) {
    CommandLine::ForCurrentProcess()->AppendLooseValue(
        UTF8ToWide(start_url_.spec()));
  }
}

void ExistingUserController::ClearCaptchaState() {
  login_token_.clear();
  login_captcha_.clear();
}

void ExistingUserController::ShowError(int error_id,
                                       const std::string& details) {
  ClearErrors();
  std::wstring error_text = l10n_util::GetString(error_id);
  if (!details.empty())
    error_text += L"\n" + ASCIIToWide(details);
  bubble_ = MessageBubble::Show(
      controllers_[selected_view_index_]->controls_window(),
      controllers_[selected_view_index_]->GetScreenBounds(),
      BubbleBorder::BOTTOM_LEFT,
      ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_WARNING),
      error_text,
      this);
}

void ExistingUserController::OnLoginSuccess(const std::string& username,
                                            const std::string& credentials) {
  AppendStartUrlToCmdline();
  if (selected_view_index_ + 1 == controllers_.size()) {
    // For new user login don't launch browser until we pass image screen.
    chromeos::LoginUtils::Get()->EnableBrowserLaunch(false);
    LoginUtils::Get()->CompleteLogin(username, credentials);
    ActivateWizard(WizardController::kUserImageScreenName);
  } else {
    // Hide the login windows now.
    STLDeleteElements(&controllers_);

    background_window_->Close();

    LoginUtils::Get()->CompleteLogin(username, credentials);
    // Delay deletion as we're on the stack.
    MessageLoop::current()->DeleteSoon(FROM_HERE, this);
  }
}

void ExistingUserController::OnOffTheRecordLoginSuccess() {
  AppendStartUrlToCmdline();
  LoginUtils::Get()->CompleteOffTheRecordLogin();
}

void ExistingUserController::OnCaptchaEntered(const std::string& captcha) {
  login_captcha_ = captcha;
}

}  // namespace chromeos
<commit_msg>Hide login entries before removing them to prevent flickering.<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/chromeos/login/existing_user_controller.h"

#include <algorithm>
#include <functional>
#include <map>

#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/message_loop.h"
#include "base/stl_util-inl.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/cros/login_library.h"
#include "chrome/browser/chromeos/cros/network_library.h"
#include "chrome/browser/chromeos/login/authenticator.h"
#include "chrome/browser/chromeos/login/background_view.h"
#include "chrome/browser/chromeos/login/helper.h"
#include "chrome/browser/chromeos/login/login_utils.h"
#include "chrome/browser/chromeos/login/message_bubble.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/browser/chromeos/wm_ipc.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/profile_manager.h"
#include "grit/theme_resources.h"
#include "views/screen.h"
#include "views/widget/widget.h"
#include "views/widget/widget_gtk.h"
#include "views/window/window.h"

namespace chromeos {

namespace {

// Max number of users we'll show. The true max is the min of this and the
// number of windows that fit on the screen.
const size_t kMaxUsers = 6;

// Used to indicate no user has been selected.
const size_t kNotSelected = -1;

// ClientLogin response parameters.
const char kError[] = "Error=";
const char kCaptchaError[] = "CaptchaRequired";
const char kCaptchaUrlParam[] = "CaptchaUrl=";
const char kCaptchaTokenParam[] = "CaptchaToken=";
const char kParamSuffix[] = "\n";

// URL prefix for CAPTCHA image.
const char kCaptchaUrlPrefix[] = "http://www.google.com/accounts/";

// Checks if display names are unique. If there are duplicates, enables
// tooltips with full emails to let users distinguish their accounts.
// Otherwise, disables the tooltips.
void EnableTooltipsIfNeeded(const std::vector<UserController*>& controllers) {
  std::map<std::string, int> visible_display_names;
  for (size_t i = 0; i + 1 < controllers.size(); ++i) {
    const std::string& display_name =
        controllers[i]->user().GetDisplayName();
    ++visible_display_names[display_name];
  }
  for (size_t i = 0; i + 1 < controllers.size(); ++i) {
    const std::string& display_name =
        controllers[i]->user().GetDisplayName();
    bool show_tooltip = visible_display_names[display_name] > 1;
    controllers[i]->EnableNameTooltip(show_tooltip);
  }
}

}  // namespace

ExistingUserController*
  ExistingUserController::delete_scheduled_instance_ = NULL;

ExistingUserController::ExistingUserController(
    const std::vector<UserManager::User>& users,
    const gfx::Rect& background_bounds)
    : background_bounds_(background_bounds),
      background_window_(NULL),
      background_view_(NULL),
      selected_view_index_(kNotSelected),
      bubble_(NULL) {
  if (delete_scheduled_instance_)
    delete_scheduled_instance_->Delete();

  // Caclulate the max number of users from available screen size.
  size_t max_users = kMaxUsers;
  int screen_width = background_bounds.width();
  if (screen_width > 0) {
    max_users = std::max(static_cast<size_t>(2), std::min(kMaxUsers,
        static_cast<size_t>((screen_width - login::kUserImageSize)
                            / (UserController::kUnselectedSize +
                               UserController::kPadding))));
  }

  size_t visible_users_count = std::min(users.size(), max_users - 1);
  for (size_t i = 0; i < visible_users_count; ++i)
    controllers_.push_back(new UserController(this, users[i]));

  // Add the view representing the guest user last.
  controllers_.push_back(new UserController(this));
}

void ExistingUserController::Init() {
  if (!background_window_) {
    background_window_ = BackgroundView::CreateWindowContainingView(
        background_bounds_,
        &background_view_);
    background_window_->Show();
  }
  for (size_t i = 0; i < controllers_.size(); ++i) {
    (controllers_[i])->Init(static_cast<int>(i),
                            static_cast<int>(controllers_.size()));
  }

  EnableTooltipsIfNeeded(controllers_);

  WmMessageListener::instance()->AddObserver(this);

  if (CrosLibrary::Get()->EnsureLoaded())
    CrosLibrary::Get()->GetLoginLibrary()->EmitLoginPromptReady();
}

void ExistingUserController::OwnBackground(
    views::Widget* background_widget,
    chromeos::BackgroundView* background_view) {
  DCHECK(!background_window_);
  background_window_ = background_widget;
  background_view_ = background_view;
}

ExistingUserController::~ExistingUserController() {
  ClearErrors();

  if (background_window_)
    background_window_->Close();

  WmMessageListener::instance()->RemoveObserver(this);

  STLDeleteElements(&controllers_);
}

void ExistingUserController::Delete() {
  delete_scheduled_instance_ = NULL;
  delete this;
}

void ExistingUserController::ProcessWmMessage(const WmIpc::Message& message,
                                              GdkWindow* window) {
  if (message.type() != WM_IPC_MESSAGE_CHROME_CREATE_GUEST_WINDOW)
    return;

  ActivateWizard(std::string());
}

void ExistingUserController::SendSetLoginState(bool is_enabled) {
  WmIpc::Message message(WM_IPC_MESSAGE_WM_SET_LOGIN_STATE);
  message.set_param(0, is_enabled);
  WmIpc::instance()->SendMessage(message);
}

void ExistingUserController::Login(UserController* source,
                                   const string16& password) {
  std::vector<UserController*>::const_iterator i =
      std::find(controllers_.begin(), controllers_.end(), source);
  DCHECK(i != controllers_.end());
  selected_view_index_ = i - controllers_.begin();

  authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
  Profile* profile = g_browser_process->profile_manager()->GetDefaultProfile();
  ChromeThread::PostTask(
      ChromeThread::UI, FROM_HERE,
      NewRunnableMethod(authenticator_.get(),
                        &Authenticator::AuthenticateToLogin,
                        profile,
                        controllers_[selected_view_index_]->user().email(),
                        UTF16ToUTF8(password),
                        login_token_,
                        login_captcha_));

  // Disable clicking on other windows.
  SendSetLoginState(false);
}

void ExistingUserController::LoginOffTheRecord() {
  authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
  ChromeThread::PostTask(
      ChromeThread::UI, FROM_HERE,
      NewRunnableMethod(authenticator_.get(),
                        &Authenticator::LoginOffTheRecord));

  // Disable clicking on other windows.
  SendSetLoginState(false);
}

void ExistingUserController::ClearErrors() {
  // bubble_ will be set to NULL in callback.
  if (bubble_)
    bubble_->Close();
}

void ExistingUserController::OnUserSelected(UserController* source) {
  std::vector<UserController*>::const_iterator i =
      std::find(controllers_.begin(), controllers_.end(), source);
  DCHECK(i != controllers_.end());
  size_t new_selected_index = i - controllers_.begin();
  if (new_selected_index != selected_view_index_ &&
      selected_view_index_ != kNotSelected) {
    controllers_[selected_view_index_]->ClearAndEnablePassword();
    ClearCaptchaState();
  }
  selected_view_index_ = new_selected_index;
}

void ExistingUserController::ActivateWizard(const std::string& screen_name) {
  // WizardController takes care of deleting itself when done.
  WizardController* controller = new WizardController();
  controller->Init(screen_name, background_bounds_);
  controller->Show();

  // Give the background window to the controller.
  controller->OwnBackground(background_window_, background_view_);
  background_window_ = NULL;

  // And schedule us for deletion. We delay for a second as the window manager
  // is doing an animation with our windows.
  DCHECK(!delete_scheduled_instance_);
  delete_scheduled_instance_ = this;
  delete_timer_.Start(base::TimeDelta::FromSeconds(1), this,
                      &ExistingUserController::Delete);
}

void ExistingUserController::RemoveUser(UserController* source) {
  ClearErrors();

  UserManager::Get()->RemoveUser(source->user().email());

  // We need to unmap entry windows, the windows will be unmapped in destructor.
  controllers_.erase(controllers_.begin() + source->user_index());
  delete source;

  EnableTooltipsIfNeeded(controllers_);
  int new_size = static_cast<int>(controllers_.size());
  for (int i = 0; i < new_size; ++i)
    controllers_[i]->UpdateUserCount(i, new_size);
}

void ExistingUserController::SelectUser(int index) {
  if (index >= 0 && index < static_cast<int>(controllers_.size()) &&
      index != static_cast<int>(selected_view_index_)) {
    WmIpc::Message message(WM_IPC_MESSAGE_WM_SELECT_LOGIN_USER);
    message.set_param(0, index);
    WmIpc::instance()->SendMessage(message);
  }
}

void ExistingUserController::OnLoginFailure(const std::string& error) {
  LOG(INFO) << "OnLoginFailure";
  ClearCaptchaState();

  // Check networking after trying to login in case user is
  // cached locally or the local admin account.
  NetworkLibrary* network = CrosLibrary::Get()->GetNetworkLibrary();
  if (!network || !CrosLibrary::Get()->EnsureLoaded()) {
    ShowError(IDS_LOGIN_ERROR_NO_NETWORK_LIBRARY, error);
  } else if (!network->Connected()) {
    ShowError(IDS_LOGIN_ERROR_OFFLINE_FAILED_NETWORK_NOT_CONNECTED, error);
  } else {
    std::string error_code = LoginUtils::ExtractClientLoginParam(error,
                                                                 kError,
                                                                 kParamSuffix);
    std::string captcha_url;
    if (error_code == kCaptchaError)
      captcha_url = LoginUtils::ExtractClientLoginParam(error,
                                                        kCaptchaUrlParam,
                                                        kParamSuffix);
    if (captcha_url.empty()) {
      ShowError(IDS_LOGIN_ERROR_AUTHENTICATING, error);
    } else {
      // Save token for next login retry.
      login_token_ = LoginUtils::ExtractClientLoginParam(error,
                                                         kCaptchaTokenParam,
                                                         kParamSuffix);
      gfx::NativeWindow parent = GTK_WINDOW(
          static_cast<views::WidgetGtk*>(background_window_)->GetNativeView());
      CaptchaView* view =
          new CaptchaView(GURL(kCaptchaUrlPrefix + captcha_url));
      view->set_delegate(this);
      views::Window* window = views::Window::CreateChromeWindow(parent,
                                                                gfx::Rect(),
                                                                view);
      window->SetIsAlwaysOnTop(true);
      window->Show();
    }
  }

  controllers_[selected_view_index_]->ClearAndEnablePassword();

  // Reenable clicking on other windows.
  SendSetLoginState(true);
}

void ExistingUserController::AppendStartUrlToCmdline() {
  if (start_url_.is_valid()) {
    CommandLine::ForCurrentProcess()->AppendLooseValue(
        UTF8ToWide(start_url_.spec()));
  }
}

void ExistingUserController::ClearCaptchaState() {
  login_token_.clear();
  login_captcha_.clear();
}

void ExistingUserController::ShowError(int error_id,
                                       const std::string& details) {
  ClearErrors();
  std::wstring error_text = l10n_util::GetString(error_id);
  if (!details.empty())
    error_text += L"\n" + ASCIIToWide(details);
  bubble_ = MessageBubble::Show(
      controllers_[selected_view_index_]->controls_window(),
      controllers_[selected_view_index_]->GetScreenBounds(),
      BubbleBorder::BOTTOM_LEFT,
      ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_WARNING),
      error_text,
      this);
}

void ExistingUserController::OnLoginSuccess(const std::string& username,
                                            const std::string& credentials) {
  AppendStartUrlToCmdline();
  if (selected_view_index_ + 1 == controllers_.size()) {
    // For new user login don't launch browser until we pass image screen.
    chromeos::LoginUtils::Get()->EnableBrowserLaunch(false);
    LoginUtils::Get()->CompleteLogin(username, credentials);
    ActivateWizard(WizardController::kUserImageScreenName);
  } else {
    // Hide the login windows now.
    WmIpc::Message message(WM_IPC_MESSAGE_WM_HIDE_LOGIN);
    WmIpc::instance()->SendMessage(message);

    LoginUtils::Get()->CompleteLogin(username, credentials);

    // Delay deletion as we're on the stack.
    MessageLoop::current()->DeleteSoon(FROM_HERE, this);
  }
}

void ExistingUserController::OnOffTheRecordLoginSuccess() {
  AppendStartUrlToCmdline();
  LoginUtils::Get()->CompleteOffTheRecordLogin();
}

void ExistingUserController::OnCaptchaEntered(const std::string& captcha) {
  login_captcha_ = captcha;
}

}  // namespace chromeos
<|endoftext|>


<commit_before>//
//  SNA.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 24/04/2021.
//  Copyright © 2021 Thomas Harte. All rights reserved.
//

#include "SNA.hpp"

using namespace Storage::State;

std::unique_ptr<Analyser::Static::Target> SNA::load(const std::string &file_name) {
	// 0x1a byte header:
	//
	//	00	I
	//	01	HL'
	//	03	DE'
	//	05	BC'
	//	07	AF'
	//	09	HL
	//	0B	DE
	//	0D	BC
	//	0F	IY
	//	11	IX
	//	13	IFF2 (in bit 2)
	//	14	R
	//	15	AF
	//	17	SP
	//	19	interrupt mode
	//	1A	border colour
	//	1B–	48kb RAM contents

	(void)file_name;
	return nullptr;
}
<commit_msg>Add further note to future self.<commit_after>//
//  SNA.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 24/04/2021.
//  Copyright © 2021 Thomas Harte. All rights reserved.
//

#include "SNA.hpp"

using namespace Storage::State;

std::unique_ptr<Analyser::Static::Target> SNA::load(const std::string &file_name) {
	// 0x1a byte header:
	//
	//	00	I
	//	01	HL'
	//	03	DE'
	//	05	BC'
	//	07	AF'
	//	09	HL
	//	0B	DE
	//	0D	BC
	//	0F	IY
	//	11	IX
	//	13	IFF2 (in bit 2)
	//	14	R
	//	15	AF
	//	17	SP
	//	19	interrupt mode
	//	1A	border colour
	//	1B–	48kb RAM contents
	//
	// (perform a POP to get the PC)

	(void)file_name;
	return nullptr;
}
<|endoftext|>