<commit_before>/* * This file is part of Maliit framework *
 *
 * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 * All rights reserved.
 *
 * Contact: maliit-discuss@lists.maliit.org
 *
 * Copyright (C) 2012 One Laptop per Child Association
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1 as published by the Free Software Foundation
 * and appearing in the file LICENSE.LGPL included in the packaging
 * of this file.
 */

#include "windowedsurface.h"
#include "windowedsurface_p.h"
#include "windowedsurfacefactory_p.h"

#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
#include "mimdummyinputcontext.h"
#endif

#include "mimapphostedserverlogic.h"

#include <maliit/plugins/abstractwidgetssurface.h>

#include <QApplication>
#include <QDebug>
#include <QDesktopWidget>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsItem>
#include <QWidget>

#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
#include <QGuiApplication>
#include <QtGui/5.0.0/QtGui/qpa/qplatformnativeinterface.h>
#include <QVariant>
#include <QWindow>
#endif

#ifdef Q_WS_X11
#include <QX11Info>
#include <X11/Xlib.h>
#endif

using Maliit::Plugins::AbstractSurface;

namespace Maliit {
namespace Server {

namespace {
    const Qt::WindowFlags g_window_flags =
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
    Qt::WindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint | Qt::WindowDoesNotAcceptFocus);
#else
    Qt::WindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint);
#endif
}

WindowedSurface::WindowedSurface(WindowedSurfaceFactory *factory,
                                 AbstractSurface::Options options,
                                 const QSharedPointer<WindowedSurface> &parent,
                                 QWidget *toplevel)
    : AbstractSurface(),
      mFactory(factory),
      mOptions(options),
      mParent(parent),
      mToplevel(toplevel),
      mActive(false),
      mVisible(false),
      mRelativePosition()
{
    QWidget *parentWidget = 0;
    if (parent) {
        parentWidget = parent->mToplevel.data();
    }
    mToplevel->setParent(parentWidget, g_window_flags);

#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
    mToplevel->setAttribute(Qt::WA_X11DoNotAcceptFocus);
#endif
    mToplevel->setAutoFillBackground(false);
    mToplevel->setBackgroundRole(QPalette::NoRole);

    mToplevel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);

    updateVisibility();
}

WindowedSurface::~WindowedSurface()
{
}

void WindowedSurface::show()
{
    mVisible = true;
    updateVisibility();
}

void WindowedSurface::hide()
{
    mVisible = false;
    updateVisibility();
}

QSize WindowedSurface::size() const
{
    return mToplevel->size();
}

void WindowedSurface::setSize(const QSize &size)
{
    const QSize& desktopSize = QApplication::desktop()->screenGeometry().size();

    if (isWindow()) {
        // stand-alone Maliit server
        if (mOptions & PositionCenterBottom) {
            mToplevel->setGeometry(QRect(QPoint((desktopSize.width() - size.width()) / 2,
                                                desktopSize.height() - size.height()), size));
        } else {
            mToplevel->resize(size);
        }
    } else {
        // application-hosted Maliit server
        mToplevel->resize(size);
    }
    mFactory->updateInputMethodArea();
}

QPoint WindowedSurface::relativePosition() const
{
    return mRelativePosition;
}

void WindowedSurface::setRelativePosition(const QPoint &position)
{
    mRelativePosition = position;
    QPoint parentPosition(0, 0);
    if (mParent) {
        if (isWindow() && !mParent->isWindow()) {
            parentPosition = mParent->mapToGlobal(QPoint(0, 0));
        } else if (!isWindow() && mParent->isWindow()) {
            // do nothing
        } else {
            parentPosition = mParent->mToplevel->pos();
        }
    }
    mToplevel->move(parentPosition + mRelativePosition);
        mFactory->updateInputMethodArea();
}

QSharedPointer<AbstractSurface> WindowedSurface::parent() const
{
    return mParent;
}

QPoint WindowedSurface::translateEventPosition(const QPoint &eventPosition,
                                               const QSharedPointer<AbstractSurface> &eventSurface) const
{
    if (!eventSurface)
        return eventPosition;

    QSharedPointer<WindowedSurface> windowedSurface = qSharedPointerDynamicCast<WindowedSurface>(eventSurface);
    if (!windowedSurface)
        return QPoint();

    return -mToplevel->pos() + eventPosition + windowedSurface->mToplevel->pos();
}

void WindowedSurface::setActive(bool active)
{
    mActive = active;
    updateVisibility();
}

void WindowedSurface::applicationFocusChanged(WId winId)
{
    if (mParent)
        return;
#ifdef Q_WS_X11
    XSetTransientForHint(QX11Info::display(),
                         mToplevel->window()->effectiveWinId(),
                         winId);
#else
    Q_UNUSED(winId);
#endif
}

QRegion WindowedSurface::inputMethodArea()
{
    if (!mToplevel->isVisible())
        return QRegion();

    return QRegion(mToplevel->geometry());
}

void WindowedSurface::updateVisibility()
{
    mToplevel->setVisible(mActive && mVisible);
    mFactory->updateInputMethodArea();
}

bool WindowedSurface::isWindow() const
{
    return mToplevel->isWindow();
}

QPoint WindowedSurface::mapToGlobal(const QPoint &pos) const
{
    return mToplevel->mapToGlobal(pos);
}

class GraphicsView : public QGraphicsView
{
public:
    GraphicsView()
        : QGraphicsView()
    {
        setWindowFlags(g_window_flags);
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
        setAttribute(Qt::WA_X11DoNotAcceptFocus);
#endif
        // Fixes: MALIIT#194 - Maliit can not input when QML viewer is set to
        // full screen on QWS without x11
        setAttribute(Qt::WA_ShowWithoutActivating);

        setAutoFillBackground(false);
        setBackgroundRole(QPalette::NoRole);
        setBackgroundBrush(Qt::transparent);

        // This is a workaround for non-compositing window managers. Apparently
        // setting this attribute while using such WMs may cause garbled
        // painting of VKB.
#ifndef DISABLE_TRANSLUCENT_BACKGROUND_HINT
        setAttribute(Qt::WA_TranslucentBackground);
#endif
        viewport()->setAutoFillBackground(false);
    }
};

class RootItem
    : public QGraphicsItem
{
private:
    QRectF m_rect;

public:
    explicit RootItem(QGraphicsItem *parent = 0)
        : QGraphicsItem(parent)
        , m_rect()
    {
        setFlag(QGraphicsItem::ItemHasNoContents);
    }

    void setRect(const QRectF &rect)
    {
        m_rect = rect;
    }

    virtual QRectF boundingRect() const
    {
        return m_rect;
    }

    virtual void paint(QPainter *,
                       const QStyleOptionGraphicsItem *,
                       QWidget *)
    {}
};

class WindowedGraphicsViewSurface : public WindowedSurface, public Maliit::Plugins::AbstractGraphicsViewSurface
{
public:
    WindowedGraphicsViewSurface(WindowedSurfaceFactory *factory, AbstractSurface::Options options, const QSharedPointer<WindowedSurface> &parent)
        : WindowedSurface(factory, options, parent, new GraphicsView),
          AbstractGraphicsViewSurface(),
          mRoot(0)
    {
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
        MIMDummyInputContext dummy;
#endif
        QGraphicsView *view = static_cast<QGraphicsView*>(mToplevel.data());
        view->setViewportUpdateMode(QGraphicsView::MinimalViewportUpdate);
        view->setOptimizationFlags(QGraphicsView::DontClipPainter | QGraphicsView::DontSavePainterState);
        view->setFrameShape(QFrame::NoFrame);
        view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
        // Calling QGraphicsView::setScene() indirectly calls QWidget::inputContext() on the view.  If there isn't
        // an input context set on the widget, this calls QApplication::inputContext(), which leads to infinite
        // recursion if surface creation happens during input method creation and QT_IM_MODULE is set (for example
        // when embedding maliit-server in the application)
        view->setInputContext(&dummy);
#endif
        QGraphicsScene *scene = new QGraphicsScene(view);
        view->setScene(scene);

#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
        view->setInputContext(0);
#endif
    }

    ~WindowedGraphicsViewSurface() {}

    QGraphicsScene *scene() const
    {
        return view()->scene();
    }

    QGraphicsView *view() const
    {
        return static_cast<QGraphicsView*>(mToplevel.data());
    }

    void show()
    {
        WindowedSurface::show();

        const QRect rect(QPoint(), mToplevel->size());

        if (not mRoot) {
            scene()->addItem(mRoot = new RootItem);
            mRoot->setRect(rect);
            mRoot->show();
        }
    }

    void setSize(const QSize &size)
    {
        WindowedSurface::setSize(size);

        view()->setSceneRect(QRect(QPoint(), mToplevel->size()));
        if (mRoot) {
            mRoot->setRect(QRect(QPoint(), mToplevel->size()));
        }
    }

    void clear()
    {
        mRoot = 0;
        scene()->clear();
    }

    QGraphicsItem *root() const
    {
        return mRoot;
    }

private:
    RootItem *mRoot;
};

class WindowedWidgetSurface : public WindowedSurface, public Maliit::Plugins::AbstractWidgetSurface
{
public:
    WindowedWidgetSurface(WindowedSurfaceFactory *factory, AbstractSurface::Options options, const QSharedPointer<WindowedSurface> &parent)
        : WindowedSurface(factory, options, parent, new QWidget),
          AbstractWidgetSurface()
    {}

    QWidget* widget() const {
        return mToplevel.data();
    }
};

WindowedSurfaceFactoryPrivate::WindowedSurfaceFactoryPrivate(WindowedSurfaceFactory *factory)
    : QObject()
    , q_ptr(factory)
    , surfaces()
    , active(false)
{
    connect(QApplication::desktop(), SIGNAL(resized(int)),
            this, SLOT(screenResized(int)));
}

void WindowedSurfaceFactoryPrivate::screenResized(int)
{
    Q_Q(WindowedSurfaceFactory);

    Q_FOREACH(QWeakPointer<WindowedSurface> weakSurface, surfaces) {
        QSharedPointer<WindowedSurface> surface = weakSurface.toStrongRef();
        if (surface) {
            surface->setSize(surface->size());
            if (surface->parent()) {
                surface->setRelativePosition(surface->relativePosition());
            }
        }
    }
    Q_EMIT q->screenSizeChanged(q->screenSize());
}

// Windowed Surface Factory

WindowedSurfaceFactory::WindowedSurfaceFactory()
    : AbstractSurfaceFactory()
    , d_ptr(new WindowedSurfaceFactoryPrivate(this))
{
}

WindowedSurfaceFactory::~WindowedSurfaceFactory()
{
}

QSize WindowedSurfaceFactory::screenSize() const
{
    return QApplication::desktop()->screenGeometry().size();
}

bool WindowedSurfaceFactory::supported(Maliit::Plugins::AbstractSurface::Options options) const
{
    return options & AbstractSurface::TypeGraphicsView;
}

QSharedPointer<AbstractSurface> WindowedSurfaceFactory::create(AbstractSurface::Options options, const QSharedPointer<AbstractSurface> &parent)
{
    QSharedPointer<WindowedSurface> defaultSurfaceParent(qSharedPointerDynamicCast<WindowedSurface>(parent));
    if (options & Maliit::Plugins::AbstractSurface::TypeGraphicsView) {
        QSharedPointer<WindowedGraphicsViewSurface> newSurface(new WindowedGraphicsViewSurface(this, options, defaultSurfaceParent));
        surfaces.push_back(newSurface);
        Q_EMIT surfaceWidgetCreated(newSurface->view(), options);
        return newSurface;
    } else if (options & Maliit::Plugins::AbstractSurface::TypeWidget) {
        QSharedPointer<WindowedWidgetSurface> newSurface(new WindowedWidgetSurface(this, options, defaultSurfaceParent));
        surfaces.push_back(newSurface);
        Q_EMIT surfaceWidgetCreated(newSurface->widget(), options);
        return newSurface;
    }
    return QSharedPointer<AbstractSurface>();
}

void WindowedSurfaceFactory::activate()
{
    Q_D(WindowedSurfaceFactory);

    d->active = true;

    Q_FOREACH(QWeakPointer<WindowedSurface> weakSurface, d->surfaces) {
        QSharedPointer<WindowedSurface> surface = weakSurface.toStrongRef();
        if (surface)
            surface->setActive(true);
    }
}

void WindowedSurfaceFactory::deactivate()
{
    Q_D(WindowedSurfaceFactory);

    d->active = false;

    Q_FOREACH(QWeakPointer<WindowedSurface> weakSurface, d->surfaces) {
        QSharedPointer<WindowedSurface> surface = weakSurface.toStrongRef();
        if (surface)
            surface->setActive(false);
    }
}

void WindowedSurfaceFactory::applicationFocusChanged(WId winId)
{
    Q_D(WindowedSurfaceFactory);

    Q_FOREACH(QWeakPointer<WindowedSurface> weakSurface, d->surfaces) {
        QSharedPointer<WindowedSurface> surface = weakSurface.toStrongRef();
        if (surface) {
            surface->applicationFocusChanged(winId);
        }
    }
}

void WindowedSurfaceFactory::updateInputMethodArea()
{
    Q_D(WindowedSurfaceFactory);

    if (!d->active)
        return;

    QRegion inputMethodArea;

    Q_FOREACH(QWeakPointer<WindowedSurface> weakSurface, d->surfaces) {
        QSharedPointer<WindowedSurface> surface = weakSurface.toStrongRef();
        if (surface && !surface->parent()) {
            inputMethodArea |= surface->inputMethodArea();
        }
    }

    Q_EMIT inputMethodAreaChanged(inputMethodArea);
}

} // namespace Server
} // namespace Maliit
<commit_msg>Deduplicate the surface creation code a bit.<commit_after>/* * This file is part of Maliit framework *
 *
 * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 * All rights reserved.
 *
 * Contact: maliit-discuss@lists.maliit.org
 *
 * Copyright (C) 2012 One Laptop per Child Association
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1 as published by the Free Software Foundation
 * and appearing in the file LICENSE.LGPL included in the packaging
 * of this file.
 */

#include "windowedsurface.h"
#include "windowedsurface_p.h"
#include "windowedsurfacefactory_p.h"

#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
#include "mimdummyinputcontext.h"
#endif

#include "mimapphostedserverlogic.h"

#include <maliit/plugins/abstractwidgetssurface.h>

#include <QApplication>
#include <QDebug>
#include <QDesktopWidget>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsItem>
#include <QWidget>

#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
#include <QGuiApplication>
#include <QtGui/5.0.0/QtGui/qpa/qplatformnativeinterface.h>
#include <QVariant>
#include <QWindow>
#endif

#ifdef Q_WS_X11
#include <QX11Info>
#include <X11/Xlib.h>
#endif

using Maliit::Plugins::AbstractSurface;

namespace Maliit {
namespace Server {

namespace {
    const Qt::WindowFlags g_window_flags =
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
    Qt::WindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint | Qt::WindowDoesNotAcceptFocus);
#else
    Qt::WindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint);
#endif
}

WindowedSurface::WindowedSurface(WindowedSurfaceFactory *factory,
                                 AbstractSurface::Options options,
                                 const QSharedPointer<WindowedSurface> &parent,
                                 QWidget *toplevel)
    : AbstractSurface(),
      mFactory(factory),
      mOptions(options),
      mParent(parent),
      mToplevel(toplevel),
      mActive(false),
      mVisible(false),
      mRelativePosition()
{
    QWidget *parentWidget = 0;
    if (parent) {
        parentWidget = parent->mToplevel.data();
    }
    mToplevel->setParent(parentWidget, g_window_flags);

#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
    mToplevel->setAttribute(Qt::WA_X11DoNotAcceptFocus);
#endif
    mToplevel->setAutoFillBackground(false);
    mToplevel->setBackgroundRole(QPalette::NoRole);

    mToplevel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);

    updateVisibility();
}

WindowedSurface::~WindowedSurface()
{
}

void WindowedSurface::show()
{
    mVisible = true;
    updateVisibility();
}

void WindowedSurface::hide()
{
    mVisible = false;
    updateVisibility();
}

QSize WindowedSurface::size() const
{
    return mToplevel->size();
}

void WindowedSurface::setSize(const QSize &size)
{
    const QSize& desktopSize = QApplication::desktop()->screenGeometry().size();

    if (isWindow()) {
        // stand-alone Maliit server
        if (mOptions & PositionCenterBottom) {
            mToplevel->setGeometry(QRect(QPoint((desktopSize.width() - size.width()) / 2,
                                                desktopSize.height() - size.height()), size));
        } else {
            mToplevel->resize(size);
        }
    } else {
        // application-hosted Maliit server
        mToplevel->resize(size);
    }
    mFactory->updateInputMethodArea();
}

QPoint WindowedSurface::relativePosition() const
{
    return mRelativePosition;
}

void WindowedSurface::setRelativePosition(const QPoint &position)
{
    mRelativePosition = position;
    QPoint parentPosition(0, 0);
    if (mParent) {
        if (isWindow() && !mParent->isWindow()) {
            parentPosition = mParent->mapToGlobal(QPoint(0, 0));
        } else if (!isWindow() && mParent->isWindow()) {
            // do nothing
        } else {
            parentPosition = mParent->mToplevel->pos();
        }
    }
    mToplevel->move(parentPosition + mRelativePosition);
        mFactory->updateInputMethodArea();
}

QSharedPointer<AbstractSurface> WindowedSurface::parent() const
{
    return mParent;
}

QPoint WindowedSurface::translateEventPosition(const QPoint &eventPosition,
                                               const QSharedPointer<AbstractSurface> &eventSurface) const
{
    if (!eventSurface)
        return eventPosition;

    QSharedPointer<WindowedSurface> windowedSurface = qSharedPointerDynamicCast<WindowedSurface>(eventSurface);
    if (!windowedSurface)
        return QPoint();

    return -mToplevel->pos() + eventPosition + windowedSurface->mToplevel->pos();
}

void WindowedSurface::setActive(bool active)
{
    mActive = active;
    updateVisibility();
}

void WindowedSurface::applicationFocusChanged(WId winId)
{
    if (mParent)
        return;
#ifdef Q_WS_X11
    XSetTransientForHint(QX11Info::display(),
                         mToplevel->window()->effectiveWinId(),
                         winId);
#else
    Q_UNUSED(winId);
#endif
}

QRegion WindowedSurface::inputMethodArea()
{
    if (!mToplevel->isVisible())
        return QRegion();

    return QRegion(mToplevel->geometry());
}

void WindowedSurface::updateVisibility()
{
    mToplevel->setVisible(mActive && mVisible);
    mFactory->updateInputMethodArea();
}

bool WindowedSurface::isWindow() const
{
    return mToplevel->isWindow();
}

QPoint WindowedSurface::mapToGlobal(const QPoint &pos) const
{
    return mToplevel->mapToGlobal(pos);
}

class GraphicsView : public QGraphicsView
{
public:
    GraphicsView()
        : QGraphicsView()
    {
        setWindowFlags(g_window_flags);
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
        setAttribute(Qt::WA_X11DoNotAcceptFocus);
#endif
        // Fixes: MALIIT#194 - Maliit can not input when QML viewer is set to
        // full screen on QWS without x11
        setAttribute(Qt::WA_ShowWithoutActivating);

        setAutoFillBackground(false);
        setBackgroundRole(QPalette::NoRole);
        setBackgroundBrush(Qt::transparent);

        // This is a workaround for non-compositing window managers. Apparently
        // setting this attribute while using such WMs may cause garbled
        // painting of VKB.
#ifndef DISABLE_TRANSLUCENT_BACKGROUND_HINT
        setAttribute(Qt::WA_TranslucentBackground);
#endif
        viewport()->setAutoFillBackground(false);
    }
};

class RootItem
    : public QGraphicsItem
{
private:
    QRectF m_rect;

public:
    explicit RootItem(QGraphicsItem *parent = 0)
        : QGraphicsItem(parent)
        , m_rect()
    {
        setFlag(QGraphicsItem::ItemHasNoContents);
    }

    void setRect(const QRectF &rect)
    {
        m_rect = rect;
    }

    virtual QRectF boundingRect() const
    {
        return m_rect;
    }

    virtual void paint(QPainter *,
                       const QStyleOptionGraphicsItem *,
                       QWidget *)
    {}
};

class WindowedGraphicsViewSurface : public WindowedSurface, public Maliit::Plugins::AbstractGraphicsViewSurface
{
public:
    WindowedGraphicsViewSurface(WindowedSurfaceFactory *factory, AbstractSurface::Options options, const QSharedPointer<WindowedSurface> &parent)
        : WindowedSurface(factory, options, parent, new GraphicsView),
          AbstractGraphicsViewSurface(),
          mRoot(0)
    {
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
        MIMDummyInputContext dummy;
#endif
        QGraphicsView *view = static_cast<QGraphicsView*>(mToplevel.data());
        view->setViewportUpdateMode(QGraphicsView::MinimalViewportUpdate);
        view->setOptimizationFlags(QGraphicsView::DontClipPainter | QGraphicsView::DontSavePainterState);
        view->setFrameShape(QFrame::NoFrame);
        view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
        // Calling QGraphicsView::setScene() indirectly calls QWidget::inputContext() on the view.  If there isn't
        // an input context set on the widget, this calls QApplication::inputContext(), which leads to infinite
        // recursion if surface creation happens during input method creation and QT_IM_MODULE is set (for example
        // when embedding maliit-server in the application)
        view->setInputContext(&dummy);
#endif
        QGraphicsScene *scene = new QGraphicsScene(view);
        view->setScene(scene);

#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
        view->setInputContext(0);
#endif
    }

    ~WindowedGraphicsViewSurface() {}

    QGraphicsScene *scene() const
    {
        return view()->scene();
    }

    QGraphicsView *view() const
    {
        return static_cast<QGraphicsView*>(mToplevel.data());
    }

    void show()
    {
        WindowedSurface::show();

        const QRect rect(QPoint(), mToplevel->size());

        if (not mRoot) {
            scene()->addItem(mRoot = new RootItem);
            mRoot->setRect(rect);
            mRoot->show();
        }
    }

    void setSize(const QSize &size)
    {
        WindowedSurface::setSize(size);

        view()->setSceneRect(QRect(QPoint(), mToplevel->size()));
        if (mRoot) {
            mRoot->setRect(QRect(QPoint(), mToplevel->size()));
        }
    }

    void clear()
    {
        mRoot = 0;
        scene()->clear();
    }

    QGraphicsItem *root() const
    {
        return mRoot;
    }

private:
    RootItem *mRoot;
};

class WindowedWidgetSurface : public WindowedSurface, public Maliit::Plugins::AbstractWidgetSurface
{
public:
    WindowedWidgetSurface(WindowedSurfaceFactory *factory, AbstractSurface::Options options, const QSharedPointer<WindowedSurface> &parent)
        : WindowedSurface(factory, options, parent, new QWidget),
          AbstractWidgetSurface()
    {}

    QWidget* widget() const {
        return mToplevel.data();
    }
};

WindowedSurfaceFactoryPrivate::WindowedSurfaceFactoryPrivate(WindowedSurfaceFactory *factory)
    : QObject()
    , q_ptr(factory)
    , surfaces()
    , active(false)
{
    connect(QApplication::desktop(), SIGNAL(resized(int)),
            this, SLOT(screenResized(int)));
}

void WindowedSurfaceFactoryPrivate::screenResized(int)
{
    Q_Q(WindowedSurfaceFactory);

    Q_FOREACH(QWeakPointer<WindowedSurface> weakSurface, surfaces) {
        QSharedPointer<WindowedSurface> surface = weakSurface.toStrongRef();
        if (surface) {
            surface->setSize(surface->size());
            if (surface->parent()) {
                surface->setRelativePosition(surface->relativePosition());
            }
        }
    }
    Q_EMIT q->screenSizeChanged(q->screenSize());
}

// Windowed Surface Factory

WindowedSurfaceFactory::WindowedSurfaceFactory()
    : AbstractSurfaceFactory()
    , d_ptr(new WindowedSurfaceFactoryPrivate(this))
{
}

WindowedSurfaceFactory::~WindowedSurfaceFactory()
{
}

QSize WindowedSurfaceFactory::screenSize() const
{
    return QApplication::desktop()->screenGeometry().size();
}

bool WindowedSurfaceFactory::supported(Maliit::Plugins::AbstractSurface::Options options) const
{
    return options & AbstractSurface::TypeGraphicsView;
}

namespace {

QSharedPointer<WindowedSurface> createSurface(WindowedSurfaceFactory *factory,
                                              AbstractSurface::Options options,
                                              const QSharedPointer<WindowedSurface> &parent)
{
    if (options & Maliit::Plugins::AbstractSurface::TypeGraphicsView) {
        return QSharedPointer<WindowedSurface>(new WindowedGraphicsViewSurface(factory,
                                                                               options,
                                                                               parent));
    }
    if (options & Maliit::Plugins::AbstractSurface::TypeWidget) {
        return QSharedPointer<WindowedSurface>(new WindowedWidgetSurface(factory,
                                                                         options,
                                                                         parent));
    }
    return QSharedPointer<WindowedSurface>();
}

} // unnamed namespace

QSharedPointer<AbstractSurface> WindowedSurfaceFactory::create(AbstractSurface::Options options, const QSharedPointer<AbstractSurface> &parent)
{
    Q_D(WindowedSurfaceFactory);

    QSharedPointer<WindowedSurface> default_surface_parent(qSharedPointerDynamicCast<WindowedSurface>(parent));
    QSharedPointer<WindowedSurface> new_surface(createSurface(this, options,
                                                              default_surface_parent));

    if (new_surface) {
        d->surfaces.push_back(new_surface);
        Q_EMIT surfaceWidgetCreated(new_surface->widget(), options);
    }
    return new_surface;
}

void WindowedSurfaceFactory::activate()
{
    Q_D(WindowedSurfaceFactory);

    d->active = true;

    Q_FOREACH(QWeakPointer<WindowedSurface> weakSurface, d->surfaces) {
        QSharedPointer<WindowedSurface> surface = weakSurface.toStrongRef();
        if (surface)
            surface->setActive(true);
    }
}

void WindowedSurfaceFactory::deactivate()
{
    Q_D(WindowedSurfaceFactory);

    d->active = false;

    Q_FOREACH(QWeakPointer<WindowedSurface> weakSurface, d->surfaces) {
        QSharedPointer<WindowedSurface> surface = weakSurface.toStrongRef();
        if (surface)
            surface->setActive(false);
    }
}

void WindowedSurfaceFactory::applicationFocusChanged(WId winId)
{
    Q_D(WindowedSurfaceFactory);

    Q_FOREACH(QWeakPointer<WindowedSurface> weakSurface, d->surfaces) {
        QSharedPointer<WindowedSurface> surface = weakSurface.toStrongRef();
        if (surface) {
            surface->applicationFocusChanged(winId);
        }
    }
}

void WindowedSurfaceFactory::updateInputMethodArea()
{
    Q_D(WindowedSurfaceFactory);

    if (!d->active)
        return;

    QRegion inputMethodArea;

    Q_FOREACH(QWeakPointer<WindowedSurface> weakSurface, d->surfaces) {
        QSharedPointer<WindowedSurface> surface = weakSurface.toStrongRef();
        if (surface && !surface->parent()) {
            inputMethodArea |= surface->inputMethodArea();
        }
    }

    Q_EMIT inputMethodAreaChanged(inputMethodArea);
}

} // namespace Server
} // namespace Maliit
<|endoftext|>


<commit_before>// Copyright 2010-2014 RethinkDB, all rights reserved.
#ifndef CLUSTERING_ADMINISTRATION_ISSUES_NAME_CONFLICT_HPP_
#define CLUSTERING_ADMINISTRATION_ISSUES_NAME_CONFLICT_HPP_

#include <vector>
#include <set>
#include <string>

#include "clustering/administration/issues/global.hpp"
#include "clustering/administration/metadata.hpp"
#include "http/json.hpp"
#include "rpc/semilattice/view.hpp"

// Base issue for all name conflicts (server, database, and table)
class name_conflict_issue_t : public issue_t {
public:
    name_conflict_issue_t(const issue_id_t &_issue_id,
                          const name_string_t &_conflicted_name);
    bool is_critical() const { return true; }

protected:
    template <typename map_t>
    std::vector<uuid_u> get_conflicted_ids(const map_t &metadata) const;

    const name_string_t conflicted_name;
    boost::shared_ptr<semilattice_read_view_t<cluster_semilattice_metadata_t> > metadata;
};

// Issue for server name conflicts
class server_name_conflict_issue_t : public name_conflict_issue_t {
public:
    explicit server_name_conflict_issue_t(const name_string_t &_conflicted_name);
    const datum_string_t &get_name() const { return server_name_conflict_issue_type; }

private:
    void build_info_and_description(const metadata_t &metadata,
                                    ql::datum_t *info_out,
                                    datum_string_t *desc_out) const;

    static const datum_string_t server_name_conflict_issue_type;
    static const issue_id_t base_issue_id;
};

// Issue for database name conflicts
class db_name_conflict_issue_t : public name_conflict_issue_t {
public:
    explicit db_name_conflict_issue_t(const name_string_t &_conflicted_name);
    const datum_string_t &get_name() const { return db_name_conflict_issue_type; }

private:
    void build_info_and_description(const metadata_t &metadata,
                                    ql::datum_t *info_out,
                                    datum_string_t *desc_out) const;

    static const datum_string_t db_name_conflict_issue_type;
    static const issue_id_t base_issue_id;
};

// Issue for table name conflicts
class table_name_conflict_issue_t : public name_conflict_issue_t {
public:
    table_name_conflict_issue_t(const name_string_t &_conflicted_name,
                                const database_id_t &_db_id);
    const datum_string_t &get_name() const { return table_name_conflict_issue_type; }

private:
    void build_info_and_description(const metadata_t &metadata,
                                    ql::datum_t *info_out,
                                    datum_string_t *desc_out) const;

    void build_description(const std::string &db_name,
                           const std::vector<namespace_id_t> &ids,
                           datum_string_t *desc_out) const;

    void build_info(const std::string &db_name,
                    const std::vector<namespace_id_t> &ids,
                    ql::datum_t *info_out) const;

    static const datum_string_t table_name_conflict_issue_type;
    static const issue_id_t base_issue_id;
    const database_id_t db_id;
};

class name_conflict_issue_tracker_t : public issue_tracker_t {
public:
    name_conflict_issue_tracker_t(
        issue_multiplexer_t *_parent,
        boost::shared_ptr<semilattice_read_view_t<cluster_semilattice_metadata_t> >
            _cluster_sl_view);

    ~name_conflict_issue_tracker_t();

    std::vector<scoped_ptr_t<issue_t> > get_issues() const;

private:
    boost::shared_ptr<semilattice_read_view_t<cluster_semilattice_metadata_t> >
        cluster_sl_view;

    DISABLE_COPYING(name_conflict_issue_tracker_t);
};

#endif /* CLUSTERING_ADMINISTRATION_ISSUES_NAME_CONFLICT_HPP_ */
<commit_msg>removing unused metadata field<commit_after>// Copyright 2010-2014 RethinkDB, all rights reserved.
#ifndef CLUSTERING_ADMINISTRATION_ISSUES_NAME_CONFLICT_HPP_
#define CLUSTERING_ADMINISTRATION_ISSUES_NAME_CONFLICT_HPP_

#include <vector>
#include <set>
#include <string>

#include "clustering/administration/issues/global.hpp"
#include "clustering/administration/metadata.hpp"
#include "http/json.hpp"
#include "rpc/semilattice/view.hpp"

// Base issue for all name conflicts (server, database, and table)
class name_conflict_issue_t : public issue_t {
public:
    name_conflict_issue_t(const issue_id_t &_issue_id,
                          const name_string_t &_conflicted_name);
    bool is_critical() const { return true; }

protected:
    template <typename map_t>
    std::vector<uuid_u> get_conflicted_ids(const map_t &metadata) const;

    const name_string_t conflicted_name;
};

// Issue for server name conflicts
class server_name_conflict_issue_t : public name_conflict_issue_t {
public:
    explicit server_name_conflict_issue_t(const name_string_t &_conflicted_name);
    const datum_string_t &get_name() const { return server_name_conflict_issue_type; }

private:
    void build_info_and_description(const metadata_t &metadata,
                                    ql::datum_t *info_out,
                                    datum_string_t *desc_out) const;

    static const datum_string_t server_name_conflict_issue_type;
    static const issue_id_t base_issue_id;
};

// Issue for database name conflicts
class db_name_conflict_issue_t : public name_conflict_issue_t {
public:
    explicit db_name_conflict_issue_t(const name_string_t &_conflicted_name);
    const datum_string_t &get_name() const { return db_name_conflict_issue_type; }

private:
    void build_info_and_description(const metadata_t &metadata,
                                    ql::datum_t *info_out,
                                    datum_string_t *desc_out) const;

    static const datum_string_t db_name_conflict_issue_type;
    static const issue_id_t base_issue_id;
};

// Issue for table name conflicts
class table_name_conflict_issue_t : public name_conflict_issue_t {
public:
    table_name_conflict_issue_t(const name_string_t &_conflicted_name,
                                const database_id_t &_db_id);
    const datum_string_t &get_name() const { return table_name_conflict_issue_type; }

private:
    void build_info_and_description(const metadata_t &metadata,
                                    ql::datum_t *info_out,
                                    datum_string_t *desc_out) const;

    void build_description(const std::string &db_name,
                           const std::vector<namespace_id_t> &ids,
                           datum_string_t *desc_out) const;

    void build_info(const std::string &db_name,
                    const std::vector<namespace_id_t> &ids,
                    ql::datum_t *info_out) const;

    static const datum_string_t table_name_conflict_issue_type;
    static const issue_id_t base_issue_id;
    const database_id_t db_id;
};

class name_conflict_issue_tracker_t : public issue_tracker_t {
public:
    name_conflict_issue_tracker_t(
        issue_multiplexer_t *_parent,
        boost::shared_ptr<semilattice_read_view_t<cluster_semilattice_metadata_t> >
            _cluster_sl_view);

    ~name_conflict_issue_tracker_t();

    std::vector<scoped_ptr_t<issue_t> > get_issues() const;

private:
    boost::shared_ptr<semilattice_read_view_t<cluster_semilattice_metadata_t> >
        cluster_sl_view;

    DISABLE_COPYING(name_conflict_issue_tracker_t);
};

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


<commit_before>/**
 * @file llpanelme.cpp
 * @brief Side tray "Me" (My Profile) panel
 *
 * $LicenseInfo:firstyear=2009&license=viewergpl$
 *
 * Copyright (c) 2009, Linden Research, Inc.
 *
 * Second Life Viewer Source Code
 * The source code in this file ("Source Code") is provided by Linden Lab
 * to you under the terms of the GNU General Public License, version 2.0
 * ("GPL"), unless you have obtained a separate licensing agreement
 * ("Other License"), formally executed by you and Linden Lab.  Terms of
 * the GPL can be found in doc/GPL-license.txt in this distribution, or
 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
 *
 * There are special exceptions to the terms and conditions of the GPL as
 * it is applied to this Source Code. View the full text of the exception
 * in the file doc/FLOSS-exception.txt in this software distribution, or
 * online at
 * http://secondlifegrid.net/programs/open_source/licensing/flossexception
 *
 * By copying, modifying or distributing this software, you acknowledge
 * that you have read and understood your obligations described above,
 * and agree to abide by those obligations.
 *
 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
 * COMPLETENESS OR PERFORMANCE.
 * $/LicenseInfo$
 */

#include "llviewerprecompiledheaders.h"

#include "llpanelme.h"

// Viewer includes
#include "llpanelprofile.h"
#include "llavatarconstants.h"
#include "llagent.h"
#include "llagentwearables.h"
#include "llsidetray.h"
#include "llviewercontrol.h"
#include "llviewerdisplayname.h"

// Linden libraries
#include "llavatarnamecache.h"		// IDEVO
#include "lliconctrl.h"
#include "llnotifications.h"
#include "llnotificationsutil.h"	// IDEVO
#include "lltabcontainer.h"
#include "lltexturectrl.h"

#define PICKER_SECOND_LIFE "2nd_life_pic"
#define PICKER_FIRST_LIFE "real_world_pic"
#define PANEL_PROFILE "panel_profile"

static LLRegisterPanelClassWrapper<LLPanelMyProfileEdit> t_panel_me_profile_edit("edit_profile_panel");
static LLRegisterPanelClassWrapper<LLPanelMe> t_panel_me_profile("panel_me");

LLPanelMe::LLPanelMe(void)
 : LLPanelProfile()
 , mEditPanel(NULL)
{
	setAvatarId(gAgent.getID());
}

BOOL LLPanelMe::postBuild()
{
	LLPanelProfile::postBuild();

	getTabContainer()[PANEL_PROFILE]->childSetAction("edit_profile_btn", boost::bind(&LLPanelMe::onEditProfileClicked, this), this);
	getTabContainer()[PANEL_PROFILE]->childSetAction("edit_appearance_btn", boost::bind(&LLPanelMe::onEditAppearanceClicked, this), this);

	return TRUE;
}

void LLPanelMe::onOpen(const LLSD& key)
{
	LLPanelProfile::onOpen(key);

	// Force Edit My Profile if this is the first time when user is opening Me Panel (EXT-5068)
	bool opened = gSavedSettings.getBOOL("MePanelOpened");
	// In some cases Side Tray my call onOpen() twice, check getCollapsed() to be sure this
	// is the last time onOpen() is called
	if( !opened && !LLSideTray::getInstance()->getCollapsed() )
	{
		buildEditPanel();
		openPanel(mEditPanel, getAvatarId());

		gSavedSettings.setBOOL("MePanelOpened", true);
	}
}

bool LLPanelMe::notifyChildren(const LLSD& info)
{
	if (info.has("task-panel-action") && info["task-panel-action"].asString() == "handle-tri-state")
	{
		// Implement task panel tri-state behavior.
		//
		// When the button of an active open task panel is clicked, side tray
		// calls notifyChildren() on the panel, passing task-panel-action=>handle-tri-state as an argument.
		// The task panel is supposed to handle this by reverting to the default view,
		// i.e. closing any dependent panels like "pick info" or "profile edit".

		bool on_default_view = true;

		const LLRect& task_panel_rect = getRect();
		for (LLView* child = getFirstChild(); child; child = findNextSibling(child))
		{
			LLPanel* panel = dynamic_cast<LLPanel*>(child);
			if (!panel)
				continue;

			// *HACK: implement panel stack instead (e.g. me->pick_info->pick_edit).
			if (panel->getRect().getWidth()  == task_panel_rect.getWidth()  &&
				panel->getRect().getHeight() == task_panel_rect.getHeight() &&
				panel->getVisible())
			{
				panel->setVisible(FALSE);
				on_default_view = false;
			}
		}

		if (on_default_view)
			LLSideTray::getInstance()->collapseSideBar();

		return true; // this notification is only supposed to be handled by task panels
	}

	return LLPanel::notifyChildren(info);
}

void LLPanelMe::buildEditPanel()
{
	if (NULL == mEditPanel)
	{
		mEditPanel = new LLPanelMyProfileEdit();
		mEditPanel->childSetAction("save_btn", boost::bind(&LLPanelMe::onSaveChangesClicked, this), this);
		mEditPanel->childSetAction("cancel_btn", boost::bind(&LLPanelMe::onCancelClicked, this), this);
	}
}

void LLPanelMe::onEditProfileClicked()
{
	buildEditPanel();
	togglePanel(mEditPanel, getAvatarId()); // open
}

void LLPanelMe::onEditAppearanceClicked()
{
	if (gAgentWearables.areWearablesLoaded())
	{
		gAgent.changeCameraToCustomizeAvatar();
	}
}

void LLPanelMe::onSaveChangesClicked()
{
	LLAvatarData data = LLAvatarData();
	data.avatar_id = gAgent.getID();
	data.image_id = mEditPanel->getChild<LLTextureCtrl>(PICKER_SECOND_LIFE)->getImageAssetID();
	data.fl_image_id = mEditPanel->getChild<LLTextureCtrl>(PICKER_FIRST_LIFE)->getImageAssetID();
	data.about_text = mEditPanel->childGetValue("sl_description_edit").asString();
	data.fl_about_text = mEditPanel->childGetValue("fl_description_edit").asString();
	data.profile_url = mEditPanel->childGetValue("homepage_edit").asString();
	data.allow_publish = mEditPanel->childGetValue("show_in_search_checkbox");

	LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesUpdate(&data);
	togglePanel(mEditPanel); // close
	onOpen(getAvatarId());
}

void LLPanelMe::onCancelClicked()
{
	togglePanel(mEditPanel); // close
}

//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////

LLPanelMyProfileEdit::LLPanelMyProfileEdit()
 : LLPanelMyProfile()
{
	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_edit_profile.xml");

	setAvatarId(gAgent.getID());
}

void LLPanelMyProfileEdit::onOpen(const LLSD& key)
{
	resetData();

	// Disable editing until data is loaded, or edited fields will be overwritten when data
	// is loaded.
	enableEditing(false);
	LLPanelMyProfile::onOpen(getAvatarId());
}

void LLPanelMyProfileEdit::processProperties(void* data, EAvatarProcessorType type)
{
	if(APT_PROPERTIES == type)
	{
		const LLAvatarData* avatar_data = static_cast<const LLAvatarData*>(data);
		if(avatar_data && getAvatarId() == avatar_data->avatar_id)
		{
			// *TODO dzaporozhan
			// Workaround for ticket EXT-1099, waiting for fix for ticket EXT-1128
			enableEditing(true);
			processProfileProperties(avatar_data);
			LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(),this);
		}
	}
}

void LLPanelMyProfileEdit::processProfileProperties(const LLAvatarData* avatar_data)
{
	fillCommonData(avatar_data);

	// 'Home page' was hidden in LLPanelAvatarProfile::fillCommonData() to fix  EXT-4734
	// Show 'Home page' in Edit My Profile (EXT-4873)
	childSetVisible("homepage_edit", true);

	fillPartnerData(avatar_data);

	fillAccountStatus(avatar_data);

	childSetValue("show_in_search_checkbox", (BOOL)(avatar_data->flags & AVATAR_ALLOW_PUBLISH));

	// IDEVO - These fields do not seem to exist any more.
	//std::string full_name;
	//BOOL found = gCacheName->getFullName(avatar_data->avatar_id, full_name);
	//if (found)
	//{
	//	childSetTextArg("name_text", "[NAME]", full_name);
	//}
	LLAvatarNameCache::get(avatar_data->avatar_id,
		boost::bind(&LLPanelMyProfileEdit::onNameCache, this, _1, _2));
}

void LLPanelMyProfileEdit::onNameCache(const LLUUID& agent_id, const LLAvatarName& av_name)
{
	getChild<LLUICtrl>("user_name")->setValue( av_name.mDisplayName );
	getChild<LLUICtrl>("user_slid")->setValue( av_name.mSLID );
}

BOOL LLPanelMyProfileEdit::postBuild()
{
	initTexturePickerMouseEvents();

	childSetTextArg("partner_edit_link", "[URL]", getString("partner_edit_link_url"));
	childSetTextArg("my_account_link", "[URL]", getString("my_account_link_url"));

	getChild<LLUICtrl>("set_name")->setCommitCallback(
		boost::bind(&LLPanelMyProfileEdit::onClickSetName, this));

	return LLPanelAvatarProfile::postBuild();
}
/**
 * Inits map with texture picker and appropriate edit icon.
 * Sets callbacks of Mouse Enter and Mouse Leave signals of Texture Pickers
 */
void LLPanelMyProfileEdit::initTexturePickerMouseEvents()
{
	LLTextureCtrl* text_pic = getChild<LLTextureCtrl>(PICKER_SECOND_LIFE);
	LLIconCtrl* text_icon = getChild<LLIconCtrl>("2nd_life_edit_icon");
	mTextureEditIconMap[text_pic->getName()] = text_icon;
	text_pic->setMouseEnterCallback(boost::bind(&LLPanelMyProfileEdit::onTexturePickerMouseEnter, this, _1));
	text_pic->setMouseLeaveCallback(boost::bind(&LLPanelMyProfileEdit::onTexturePickerMouseLeave, this, _1));
	text_icon->setVisible(FALSE);

	text_pic = getChild<LLTextureCtrl>(PICKER_FIRST_LIFE);
	text_icon = getChild<LLIconCtrl>("real_world_edit_icon");
	mTextureEditIconMap[text_pic->getName()] = text_icon;
	text_pic->setMouseEnterCallback(boost::bind(&LLPanelMyProfileEdit::onTexturePickerMouseEnter, this, _1));
	text_pic->setMouseLeaveCallback(boost::bind(&LLPanelMyProfileEdit::onTexturePickerMouseLeave, this, _1));
	text_icon->setVisible(FALSE);
}

void LLPanelMyProfileEdit::resetData()
{
	LLPanelMyProfile::resetData();

	//childSetTextArg("name_text", "[FIRST]", LLStringUtil::null);
	//childSetTextArg("name_text", "[LAST]", LLStringUtil::null);
	getChild<LLUICtrl>("user_name")->setValue( LLSD() );
	getChild<LLUICtrl>("user_slid")->setValue( LLSD() );
}

void LLPanelMyProfileEdit::onTexturePickerMouseEnter(LLUICtrl* ctrl)
{
	mTextureEditIconMap[ctrl->getName()]->setVisible(TRUE);
}
void LLPanelMyProfileEdit::onTexturePickerMouseLeave(LLUICtrl* ctrl)
{
	mTextureEditIconMap[ctrl->getName()]->setVisible(FALSE);
}

void LLPanelMyProfileEdit::onCacheSetName(bool success,
										  const std::string& reason,
										  const LLSD& content)
{
	if (success)
	{
		// Re-fetch my name, as it may have been sanitized by the service
		LLAvatarNameCache::get(getAvatarId(),
			boost::bind(&LLPanelMyProfileEdit::onNameCache, this, _1, _2));
		return;
	}

	// Request failed, notify the user
	std::string error_tag = content["error_tag"].asString();
	llinfos << "set name failure error_tag " << error_tag << llendl;

	// We might have a localized string for this message
	if (!error_tag.empty()
		&& LLNotifications::getInstance()->templateExists(error_tag))
	{
		LLNotificationsUtil::add(error_tag);
		return;
	}

	// The server error might have a localized message for us
	std::string lang_code = LLUI::getLanguage();
	LLSD error_desc = content["error_description"];
	if (error_desc.has( lang_code ))
	{
		LLSD args;
		args["MESSAGE"] = error_desc[lang_code].asString();
		LLNotificationsUtil::add("GenericAlert", args);
		return;
	}

	// No specific error, throw a generic one
	LLNotificationsUtil::add("SetDisplayNameFailedGeneric");
}

void LLPanelMyProfileEdit::onDialogSetName(const LLSD& notification, const LLSD& response)
{
	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
	if (option == 0)
	{
		LLUUID agent_id = notification["payload"]["agent_id"];
		if (agent_id.isNull()) return;

		std::string display_name = response["display_name"].asString();
		LLViewerDisplayName::set(display_name,
			boost::bind(&LLPanelMyProfileEdit::onCacheSetName, this,
				_1, _2, _3));
	}
}

void LLPanelMyProfileEdit::onClickSetName()
{
	// IDEVO
	LLUUID agent_id = getAvatarId();
	std::string display_name;
	LLAvatarName av_name;
	if (LLAvatarNameCache::useDisplayNames()
		&& LLAvatarNameCache::get(agent_id, &av_name))
	{
		display_name = av_name.mDisplayName;
	}
	else
	{
		gCacheName->getFullName(agent_id, display_name);
	}

	if (!display_name.empty())
	{
		LLSD args;
		args["DISPLAY_NAME"] = display_name;
		LLSD payload;
		payload["agent_id"] = agent_id;
		LLNotificationsUtil::add("SetDisplayName", args, payload,
			boost::bind(&LLPanelMyProfileEdit::onDialogSetName, this, _1, _2));
	}
}

void LLPanelMyProfileEdit::enableEditing(bool enable)
{
	childSetEnabled("2nd_life_pic", enable);
	childSetEnabled("real_world_pic", enable);
	childSetEnabled("sl_description_edit", enable);
	childSetEnabled("fl_description_edit", enable);
	childSetEnabled("homepage_edit", enable);
	childSetEnabled("show_in_search_checkbox", enable);
}
<commit_msg>Hide "Set Name..." button if region/grid doesn't use display names<commit_after>/**
 * @file llpanelme.cpp
 * @brief Side tray "Me" (My Profile) panel
 *
 * $LicenseInfo:firstyear=2009&license=viewergpl$
 *
 * Copyright (c) 2009, Linden Research, Inc.
 *
 * Second Life Viewer Source Code
 * The source code in this file ("Source Code") is provided by Linden Lab
 * to you under the terms of the GNU General Public License, version 2.0
 * ("GPL"), unless you have obtained a separate licensing agreement
 * ("Other License"), formally executed by you and Linden Lab.  Terms of
 * the GPL can be found in doc/GPL-license.txt in this distribution, or
 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
 *
 * There are special exceptions to the terms and conditions of the GPL as
 * it is applied to this Source Code. View the full text of the exception
 * in the file doc/FLOSS-exception.txt in this software distribution, or
 * online at
 * http://secondlifegrid.net/programs/open_source/licensing/flossexception
 *
 * By copying, modifying or distributing this software, you acknowledge
 * that you have read and understood your obligations described above,
 * and agree to abide by those obligations.
 *
 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
 * COMPLETENESS OR PERFORMANCE.
 * $/LicenseInfo$
 */

#include "llviewerprecompiledheaders.h"

#include "llpanelme.h"

// Viewer includes
#include "llpanelprofile.h"
#include "llavatarconstants.h"
#include "llagent.h"
#include "llagentwearables.h"
#include "llsidetray.h"
#include "llviewercontrol.h"
#include "llviewerdisplayname.h"

// Linden libraries
#include "llavatarnamecache.h"		// IDEVO
#include "lliconctrl.h"
#include "llnotifications.h"
#include "llnotificationsutil.h"	// IDEVO
#include "lltabcontainer.h"
#include "lltexturectrl.h"

#define PICKER_SECOND_LIFE "2nd_life_pic"
#define PICKER_FIRST_LIFE "real_world_pic"
#define PANEL_PROFILE "panel_profile"

static LLRegisterPanelClassWrapper<LLPanelMyProfileEdit> t_panel_me_profile_edit("edit_profile_panel");
static LLRegisterPanelClassWrapper<LLPanelMe> t_panel_me_profile("panel_me");

LLPanelMe::LLPanelMe(void)
 : LLPanelProfile()
 , mEditPanel(NULL)
{
	setAvatarId(gAgent.getID());
}

BOOL LLPanelMe::postBuild()
{
	LLPanelProfile::postBuild();

	getTabContainer()[PANEL_PROFILE]->childSetAction("edit_profile_btn", boost::bind(&LLPanelMe::onEditProfileClicked, this), this);
	getTabContainer()[PANEL_PROFILE]->childSetAction("edit_appearance_btn", boost::bind(&LLPanelMe::onEditAppearanceClicked, this), this);

	return TRUE;
}

void LLPanelMe::onOpen(const LLSD& key)
{
	LLPanelProfile::onOpen(key);

	// Force Edit My Profile if this is the first time when user is opening Me Panel (EXT-5068)
	bool opened = gSavedSettings.getBOOL("MePanelOpened");
	// In some cases Side Tray my call onOpen() twice, check getCollapsed() to be sure this
	// is the last time onOpen() is called
	if( !opened && !LLSideTray::getInstance()->getCollapsed() )
	{
		buildEditPanel();
		openPanel(mEditPanel, getAvatarId());

		gSavedSettings.setBOOL("MePanelOpened", true);
	}
}

bool LLPanelMe::notifyChildren(const LLSD& info)
{
	if (info.has("task-panel-action") && info["task-panel-action"].asString() == "handle-tri-state")
	{
		// Implement task panel tri-state behavior.
		//
		// When the button of an active open task panel is clicked, side tray
		// calls notifyChildren() on the panel, passing task-panel-action=>handle-tri-state as an argument.
		// The task panel is supposed to handle this by reverting to the default view,
		// i.e. closing any dependent panels like "pick info" or "profile edit".

		bool on_default_view = true;

		const LLRect& task_panel_rect = getRect();
		for (LLView* child = getFirstChild(); child; child = findNextSibling(child))
		{
			LLPanel* panel = dynamic_cast<LLPanel*>(child);
			if (!panel)
				continue;

			// *HACK: implement panel stack instead (e.g. me->pick_info->pick_edit).
			if (panel->getRect().getWidth()  == task_panel_rect.getWidth()  &&
				panel->getRect().getHeight() == task_panel_rect.getHeight() &&
				panel->getVisible())
			{
				panel->setVisible(FALSE);
				on_default_view = false;
			}
		}

		if (on_default_view)
			LLSideTray::getInstance()->collapseSideBar();

		return true; // this notification is only supposed to be handled by task panels
	}

	return LLPanel::notifyChildren(info);
}

void LLPanelMe::buildEditPanel()
{
	if (NULL == mEditPanel)
	{
		mEditPanel = new LLPanelMyProfileEdit();
		mEditPanel->childSetAction("save_btn", boost::bind(&LLPanelMe::onSaveChangesClicked, this), this);
		mEditPanel->childSetAction("cancel_btn", boost::bind(&LLPanelMe::onCancelClicked, this), this);
	}
}

void LLPanelMe::onEditProfileClicked()
{
	buildEditPanel();
	togglePanel(mEditPanel, getAvatarId()); // open
}

void LLPanelMe::onEditAppearanceClicked()
{
	if (gAgentWearables.areWearablesLoaded())
	{
		gAgent.changeCameraToCustomizeAvatar();
	}
}

void LLPanelMe::onSaveChangesClicked()
{
	LLAvatarData data = LLAvatarData();
	data.avatar_id = gAgent.getID();
	data.image_id = mEditPanel->getChild<LLTextureCtrl>(PICKER_SECOND_LIFE)->getImageAssetID();
	data.fl_image_id = mEditPanel->getChild<LLTextureCtrl>(PICKER_FIRST_LIFE)->getImageAssetID();
	data.about_text = mEditPanel->childGetValue("sl_description_edit").asString();
	data.fl_about_text = mEditPanel->childGetValue("fl_description_edit").asString();
	data.profile_url = mEditPanel->childGetValue("homepage_edit").asString();
	data.allow_publish = mEditPanel->childGetValue("show_in_search_checkbox");

	LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesUpdate(&data);
	togglePanel(mEditPanel); // close
	onOpen(getAvatarId());
}

void LLPanelMe::onCancelClicked()
{
	togglePanel(mEditPanel); // close
}

//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////

LLPanelMyProfileEdit::LLPanelMyProfileEdit()
 : LLPanelMyProfile()
{
	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_edit_profile.xml");

	setAvatarId(gAgent.getID());
}

void LLPanelMyProfileEdit::onOpen(const LLSD& key)
{
	resetData();

	// Disable editing until data is loaded, or edited fields will be overwritten when data
	// is loaded.
	enableEditing(false);

	// Only allow changing name if this region/grid supports it
	bool use_display_names = LLAvatarNameCache::useDisplayNames();
	LLUICtrl* set_name = getChild<LLUICtrl>("set_name");
	set_name->setVisible(use_display_names);
	set_name->setEnabled(use_display_names);

	LLPanelMyProfile::onOpen(getAvatarId());
}

void LLPanelMyProfileEdit::processProperties(void* data, EAvatarProcessorType type)
{
	if(APT_PROPERTIES == type)
	{
		const LLAvatarData* avatar_data = static_cast<const LLAvatarData*>(data);
		if(avatar_data && getAvatarId() == avatar_data->avatar_id)
		{
			// *TODO dzaporozhan
			// Workaround for ticket EXT-1099, waiting for fix for ticket EXT-1128
			enableEditing(true);
			processProfileProperties(avatar_data);
			LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(),this);
		}
	}
}

void LLPanelMyProfileEdit::processProfileProperties(const LLAvatarData* avatar_data)
{
	fillCommonData(avatar_data);

	// 'Home page' was hidden in LLPanelAvatarProfile::fillCommonData() to fix  EXT-4734
	// Show 'Home page' in Edit My Profile (EXT-4873)
	childSetVisible("homepage_edit", true);

	fillPartnerData(avatar_data);

	fillAccountStatus(avatar_data);

	childSetValue("show_in_search_checkbox", (BOOL)(avatar_data->flags & AVATAR_ALLOW_PUBLISH));

	// IDEVO - These fields do not seem to exist any more.
	//std::string full_name;
	//BOOL found = gCacheName->getFullName(avatar_data->avatar_id, full_name);
	//if (found)
	//{
	//	childSetTextArg("name_text", "[NAME]", full_name);
	//}
	LLAvatarNameCache::get(avatar_data->avatar_id,
		boost::bind(&LLPanelMyProfileEdit::onNameCache, this, _1, _2));
}

void LLPanelMyProfileEdit::onNameCache(const LLUUID& agent_id, const LLAvatarName& av_name)
{
	getChild<LLUICtrl>("user_name")->setValue( av_name.mDisplayName );
	getChild<LLUICtrl>("user_slid")->setValue( av_name.mSLID );
}

BOOL LLPanelMyProfileEdit::postBuild()
{
	initTexturePickerMouseEvents();

	childSetTextArg("partner_edit_link", "[URL]", getString("partner_edit_link_url"));
	childSetTextArg("my_account_link", "[URL]", getString("my_account_link_url"));

	getChild<LLUICtrl>("set_name")->setCommitCallback(
		boost::bind(&LLPanelMyProfileEdit::onClickSetName, this));

	return LLPanelAvatarProfile::postBuild();
}
/**
 * Inits map with texture picker and appropriate edit icon.
 * Sets callbacks of Mouse Enter and Mouse Leave signals of Texture Pickers
 */
void LLPanelMyProfileEdit::initTexturePickerMouseEvents()
{
	LLTextureCtrl* text_pic = getChild<LLTextureCtrl>(PICKER_SECOND_LIFE);
	LLIconCtrl* text_icon = getChild<LLIconCtrl>("2nd_life_edit_icon");
	mTextureEditIconMap[text_pic->getName()] = text_icon;
	text_pic->setMouseEnterCallback(boost::bind(&LLPanelMyProfileEdit::onTexturePickerMouseEnter, this, _1));
	text_pic->setMouseLeaveCallback(boost::bind(&LLPanelMyProfileEdit::onTexturePickerMouseLeave, this, _1));
	text_icon->setVisible(FALSE);

	text_pic = getChild<LLTextureCtrl>(PICKER_FIRST_LIFE);
	text_icon = getChild<LLIconCtrl>("real_world_edit_icon");
	mTextureEditIconMap[text_pic->getName()] = text_icon;
	text_pic->setMouseEnterCallback(boost::bind(&LLPanelMyProfileEdit::onTexturePickerMouseEnter, this, _1));
	text_pic->setMouseLeaveCallback(boost::bind(&LLPanelMyProfileEdit::onTexturePickerMouseLeave, this, _1));
	text_icon->setVisible(FALSE);
}

void LLPanelMyProfileEdit::resetData()
{
	LLPanelMyProfile::resetData();

	//childSetTextArg("name_text", "[FIRST]", LLStringUtil::null);
	//childSetTextArg("name_text", "[LAST]", LLStringUtil::null);
	getChild<LLUICtrl>("user_name")->setValue( LLSD() );
	getChild<LLUICtrl>("user_slid")->setValue( LLSD() );
}

void LLPanelMyProfileEdit::onTexturePickerMouseEnter(LLUICtrl* ctrl)
{
	mTextureEditIconMap[ctrl->getName()]->setVisible(TRUE);
}
void LLPanelMyProfileEdit::onTexturePickerMouseLeave(LLUICtrl* ctrl)
{
	mTextureEditIconMap[ctrl->getName()]->setVisible(FALSE);
}

void LLPanelMyProfileEdit::onCacheSetName(bool success,
										  const std::string& reason,
										  const LLSD& content)
{
	if (success)
	{
		// Re-fetch my name, as it may have been sanitized by the service
		LLAvatarNameCache::get(getAvatarId(),
			boost::bind(&LLPanelMyProfileEdit::onNameCache, this, _1, _2));
		return;
	}

	// Request failed, notify the user
	std::string error_tag = content["error_tag"].asString();
	llinfos << "set name failure error_tag " << error_tag << llendl;

	// We might have a localized string for this message
	if (!error_tag.empty()
		&& LLNotifications::getInstance()->templateExists(error_tag))
	{
		LLNotificationsUtil::add(error_tag);
		return;
	}

	// The server error might have a localized message for us
	std::string lang_code = LLUI::getLanguage();
	LLSD error_desc = content["error_description"];
	if (error_desc.has( lang_code ))
	{
		LLSD args;
		args["MESSAGE"] = error_desc[lang_code].asString();
		LLNotificationsUtil::add("GenericAlert", args);
		return;
	}

	// No specific error, throw a generic one
	LLNotificationsUtil::add("SetDisplayNameFailedGeneric");
}

void LLPanelMyProfileEdit::onDialogSetName(const LLSD& notification, const LLSD& response)
{
	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
	if (option == 0)
	{
		LLUUID agent_id = notification["payload"]["agent_id"];
		if (agent_id.isNull()) return;

		std::string display_name = response["display_name"].asString();
		LLViewerDisplayName::set(display_name,
			boost::bind(&LLPanelMyProfileEdit::onCacheSetName, this,
				_1, _2, _3));
	}
}

void LLPanelMyProfileEdit::onClickSetName()
{
	// IDEVO
	LLUUID agent_id = getAvatarId();
	std::string display_name;
	LLAvatarName av_name;
	if (LLAvatarNameCache::useDisplayNames()
		&& LLAvatarNameCache::get(agent_id, &av_name))
	{
		display_name = av_name.mDisplayName;
	}
	else
	{
		gCacheName->getFullName(agent_id, display_name);
	}

	if (!display_name.empty())
	{
		LLSD args;
		args["DISPLAY_NAME"] = display_name;
		LLSD payload;
		payload["agent_id"] = agent_id;
		LLNotificationsUtil::add("SetDisplayName", args, payload,
			boost::bind(&LLPanelMyProfileEdit::onDialogSetName, this, _1, _2));
	}
}

void LLPanelMyProfileEdit::enableEditing(bool enable)
{
	childSetEnabled("2nd_life_pic", enable);
	childSetEnabled("real_world_pic", enable);
	childSetEnabled("sl_description_edit", enable);
	childSetEnabled("fl_description_edit", enable);
	childSetEnabled("homepage_edit", enable);
	childSetEnabled("show_in_search_checkbox", enable);
}
<|endoftext|>


<commit_before>#include <gtest/gtest.h>
#include <esn/network_nsli.hpp>
#include <esn/network.hpp>
#include <random>

TEST( ESN, CreateNetworkNSLI )
{
    ESN::NetworkParamsNSLI params;
    params.inputCount = 10;
    params.neuronCount = 100;
    params.outputCount = 10;
    std::unique_ptr< ESN::Network > network = CreateNetwork( params );
}

TEST(ESN, SetInputs)
{
    ESN::NetworkParamsNSLI params;
    params.inputCount = 25;
    params.neuronCount = 100;
    params.outputCount = 17;
    auto network = CreateNetwork( params );

    std::default_random_engine randomEngine;
    std::uniform_real_distribution<float > randomDist( -1.0f, 1.0f );
    std::vector< float > inputs( params.inputCount );
    for (int s = 0; s < 100; ++ s)
    {
        for (int i = 0; i < params.inputCount; ++ i)
            inputs[i] = randomDist(randomEngine);
        network->SetInputs(inputs);
    }
}

TEST( ESN, StepNSLI )
{
    ESN::NetworkParamsNSLI params;
    params.inputCount = 11;
    params.neuronCount = 100;
    params.outputCount = 15;
    std::unique_ptr< ESN::Network > network = CreateNetwork( params );
    network->Step( 0.1f );
}

TEST( ESN, TrainNSLI )
{
    const unsigned kSampleCount = 100;

    ESN::NetworkParamsNSLI params;
    params.inputCount = 1;
    params.neuronCount = 100;
    params.outputCount = 1;
    auto network = CreateNetwork( params );

    std::vector< std::vector< float > > inputs( kSampleCount );
    std::vector< std::vector< float > > outputs( kSampleCount );
    for ( int i = 0; i < kSampleCount; ++ i )
    {
        inputs[i].resize( params.inputCount );
        inputs[i][0] = 1.0f;
        outputs[i].resize( params.outputCount );
        outputs[i][0] = 1.0f;
    }

    network->Train( inputs, outputs );
}
<commit_msg>add test case ESN.TrainOnline<commit_after>#include <gtest/gtest.h>
#include <esn/network_nsli.hpp>
#include <esn/network.hpp>
#include <random>

TEST( ESN, CreateNetworkNSLI )
{
    ESN::NetworkParamsNSLI params;
    params.inputCount = 10;
    params.neuronCount = 100;
    params.outputCount = 10;
    std::unique_ptr< ESN::Network > network = CreateNetwork( params );
}

TEST(ESN, SetInputs)
{
    ESN::NetworkParamsNSLI params;
    params.inputCount = 25;
    params.neuronCount = 100;
    params.outputCount = 17;
    auto network = CreateNetwork( params );

    std::default_random_engine randomEngine;
    std::uniform_real_distribution<float > randomDist( -1.0f, 1.0f );
    std::vector< float > inputs( params.inputCount );
    for (int s = 0; s < 100; ++ s)
    {
        for (int i = 0; i < params.inputCount; ++ i)
            inputs[i] = randomDist(randomEngine);
        network->SetInputs(inputs);
    }
}

TEST( ESN, StepNSLI )
{
    ESN::NetworkParamsNSLI params;
    params.inputCount = 11;
    params.neuronCount = 100;
    params.outputCount = 15;
    std::unique_ptr< ESN::Network > network = CreateNetwork( params );
    network->Step( 0.1f );
}

TEST( ESN, TrainNSLI )
{
    const unsigned kSampleCount = 100;

    ESN::NetworkParamsNSLI params;
    params.inputCount = 1;
    params.neuronCount = 100;
    params.outputCount = 1;
    auto network = CreateNetwork( params );

    std::vector< std::vector< float > > inputs( kSampleCount );
    std::vector< std::vector< float > > outputs( kSampleCount );
    for ( int i = 0; i < kSampleCount; ++ i )
    {
        inputs[i].resize( params.inputCount );
        inputs[i][0] = 1.0f;
        outputs[i].resize( params.outputCount );
        outputs[i][0] = 1.0f;
    }

    network->Train( inputs, outputs );
}

TEST(ESN, TrainOnline)
{
    ESN::NetworkParamsNSLI params;
    params.inputCount = 32;
    params.neuronCount = 64;
    params.outputCount = 16;
    auto network = CreateNetwork(params);

    std::default_random_engine randomEngine;
    std::uniform_real_distribution<float> randomDist(-0.5f, 0.5f);
    std::vector<float> inputs(params.inputCount);
    std::vector<float> outputs(params.outputCount);
    for (int s = 0; s < 100; ++ s)
    {
        for (int i = 0; i < params.inputCount; ++ i)
            inputs[i] = randomDist(randomEngine);
        for (int i = 0; i < params.outputCount; ++ i)
            outputs[i] = randomDist(randomEngine);
        network->SetInputs(inputs);
        network->Step(1.0f);
        network->TrainOnline(outputs, false);
    }
}
<|endoftext|>


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

#include <cstring> // for memcpy()
#include <string>

#include <sampgdk/logprintf.h>
#include <sampgdk/plugin/plugin.h>
#include <sampgdk/wrapper/callbacks.h>
#include <sampgdk/wrapper/wrapper.h>

#include "jump.h"

#define AMX_EXEC_CHEAT (-10)

extern void *pAMXFunctions;

static uint32_t amx_Register_addr;
static unsigned char amx_Register_code[5];

static int Register(AMX *amx, AMX_NATIVE_INFO *nativelist, int number) {
    std::memcpy(reinterpret_cast<void*>(::amx_Register_addr), ::amx_Register_code, 5);

    int error = amx_Register(amx, nativelist, number);

    for (int i = 0; nativelist[i].name != 0 && (i < number || number == -1); ++i) {
        sampgdk::Wrapper::GetInstance()->SetNative(nativelist[i].name, nativelist[i].func);
    }

    SetJump(reinterpret_cast<void*>(::amx_Register_addr), (void*)Register, ::amx_Register_code);

    return error;
}

static uint32_t amx_FindPublic_addr;
static unsigned char amx_FindPublic_code[5];

static AMX *pGamemode = 0;
static std::string lastPublicName;

static int FindPublic(AMX *amx, const char *name, int *index) {
    std::memcpy(reinterpret_cast<void*>(::amx_FindPublic_addr), ::amx_FindPublic_code, 5);

    int error = amx_FindPublic(amx, name, index);

    if (amx == ::pGamemode && ::pGamemode != 0) {
        if (error != AMX_ERR_NONE) {
            *index = AMX_EXEC_CHEAT;
            error = AMX_ERR_NONE;
        }
        ::lastPublicName = name;
    }

    SetJump(reinterpret_cast<void*>(::amx_FindPublic_addr), (void*)FindPublic, ::amx_FindPublic_code);

    return error;
}

static uint32_t amx_Exec_addr;
static unsigned char amx_Exec_code[5];

static int Exec(AMX *amx, cell *retval, int index) {
    std::memcpy(reinterpret_cast<void*>(::amx_Exec_addr), ::amx_Exec_code, 5);

    bool canDoExec = true;

    if (index == AMX_EXEC_MAIN) {
        ::pGamemode = amx;
        canDoExec = sampgdk::Wrapper::GetInstance()->ExecutePublicHook(::pGamemode, retval, "OnGameModeInit");
    }

    if (amx == ::pGamemode && ::pGamemode != 0) {
        if (index != AMX_EXEC_MAIN && index != AMX_EXEC_CONT) {
            canDoExec = sampgdk::Wrapper::GetInstance()->ExecutePublicHook(::pGamemode, retval, ::lastPublicName);
        }
    }

    int error = AMX_ERR_NONE;

    if (canDoExec) {
        error = amx_Exec(amx, retval, index);
    }
    if (!canDoExec || (index == AMX_EXEC_CHEAT && error == AMX_ERR_INDEX)) {
        amx->stk += amx->paramcount * sizeof(cell);
    }

    SetJump(reinterpret_cast<void*>(::amx_Exec_addr), (void*)Exec, ::amx_Exec_code);

    return error;
}

namespace sampgdk {

PublicHook::PublicHook(PublicHook::Handler handler, cell breakingReturn)
    : handler_(handler), breakingReturn_(breakingReturn)
{
}

bool PublicHook::Execute(AMX *amx, cell *retval) const
{
    return ((*retval = handler_(amx)) != breakingReturn_);
}

Wrapper::Wrapper() {}

Wrapper *Wrapper::GetInstance() {
    static Wrapper w;
    return &w;
}

void Wrapper::Initialize(void **ppPluginData) {
    ::pAMXFunctions = ppPluginData[PLUGIN_DATA_AMX_EXPORTS];
    logprintf = (logprintf_t)ppPluginData[PLUGIN_DATA_LOGPRINTF];

    ::amx_Register_addr = reinterpret_cast<uint32_t>((static_cast<void**>(pAMXFunctions))[PLUGIN_AMX_EXPORT_Register]);
    SetJump(reinterpret_cast<void*>(::amx_Register_addr), (void*)Register, ::amx_Register_code);

    ::amx_FindPublic_addr = reinterpret_cast<uint32_t>((static_cast<void**>(pAMXFunctions))[PLUGIN_AMX_EXPORT_FindPublic]);
    SetJump(reinterpret_cast<void*>(::amx_FindPublic_addr), (void*)FindPublic, ::amx_FindPublic_code);

    ::amx_Exec_addr = reinterpret_cast<uint32_t>((static_cast<void**>(pAMXFunctions))[PLUGIN_AMX_EXPORT_Exec]);
    SetJump(reinterpret_cast<void*>(::amx_Exec_addr), (void*)Exec, ::amx_Exec_code);

    sampgdk::InitializeCallbacks();
}

void Wrapper::SetNative(const std::string &name, AMX_NATIVE native) {
    if (!name.empty()) {
        natives_[name] = native;
    }
}

AMX_NATIVE Wrapper::GetNative(const std::string &name) const {
    std::map<std::string, AMX_NATIVE>::const_iterator it = natives_.find(name);
    if (it != natives_.end()) {
        return it->second;
    }
    return 0;
}

void Wrapper::SetPublicHook(const std::string &name, PublicHook handler) {
    publicHooks_.insert(std::make_pair(name, handler));
}

bool Wrapper::ExecutePublicHook(AMX *amx, cell *retval, const std::string &name) const {
    std::map<std::string, PublicHook>::const_iterator it = publicHooks_.find(name);
    if (it != publicHooks_.end()) {
        return it->second.Execute(amx, retval);
    }
    return true;
}

} // namespace sampgdk

<commit_msg>Restructure code inside Exec to make it clearer<commit_after>// Copyright (c) 2011 Zeex
//
// 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.

#include <cstring> // for memcpy()
#include <string>

#include <sampgdk/logprintf.h>
#include <sampgdk/plugin/plugin.h>
#include <sampgdk/wrapper/callbacks.h>
#include <sampgdk/wrapper/wrapper.h>

#include "jump.h"

#define AMX_EXEC_CHEAT (-10)

extern void *pAMXFunctions;

static uint32_t amx_Register_addr;
static unsigned char amx_Register_code[5];

static int Register(AMX *amx, AMX_NATIVE_INFO *nativelist, int number) {
    std::memcpy(reinterpret_cast<void*>(::amx_Register_addr), ::amx_Register_code, 5);

    int error = amx_Register(amx, nativelist, number);

    for (int i = 0; nativelist[i].name != 0 && (i < number || number == -1); ++i) {
        sampgdk::Wrapper::GetInstance()->SetNative(nativelist[i].name, nativelist[i].func);
    }

    SetJump(reinterpret_cast<void*>(::amx_Register_addr), (void*)Register, ::amx_Register_code);

    return error;
}

static uint32_t amx_FindPublic_addr;
static unsigned char amx_FindPublic_code[5];

static AMX *pGamemode = 0;
static std::string lastPublicName;

static int FindPublic(AMX *amx, const char *name, int *index) {
    std::memcpy(reinterpret_cast<void*>(::amx_FindPublic_addr), ::amx_FindPublic_code, 5);

    int error = amx_FindPublic(amx, name, index);

    if (amx == ::pGamemode && ::pGamemode != 0) {
        if (error != AMX_ERR_NONE) {
            *index = AMX_EXEC_CHEAT;
            error = AMX_ERR_NONE;
        }
        ::lastPublicName = name;
    }

    SetJump(reinterpret_cast<void*>(::amx_FindPublic_addr), (void*)FindPublic, ::amx_FindPublic_code);

    return error;
}

static uint32_t amx_Exec_addr;
static unsigned char amx_Exec_code[5];

static int Exec(AMX *amx, cell *retval, int index) {
    std::memcpy(reinterpret_cast<void*>(::amx_Exec_addr), ::amx_Exec_code, 5);

    if (index == AMX_EXEC_MAIN) {
        ::pGamemode = amx;
        sampgdk::Wrapper::GetInstance()->ExecutePublicHook(::pGamemode, retval, "OnGameModeInit");
    }

    int error = AMX_ERR_NONE;

    if (amx == ::pGamemode && ::pGamemode != 0) {
        if (index != AMX_EXEC_MAIN && index != AMX_EXEC_CONT) {
            bool canDoExec = sampgdk::Wrapper::GetInstance()->ExecutePublicHook(
                ::pGamemode, retval, ::lastPublicName);
            if (canDoExec) {
                error = amx_Exec(amx, retval, index);
                if (error == AMX_ERR_INDEX && index == AMX_EXEC_CHEAT) {
                    error = AMX_ERR_NONE;
                }
            }
        }
    } else {
        error = amx_Exec(amx, retval, index);
    }

    SetJump(reinterpret_cast<void*>(::amx_Exec_addr), (void*)Exec, ::amx_Exec_code);

    return error;
}

namespace sampgdk {

PublicHook::PublicHook(PublicHook::Handler handler, cell breakingReturn)
    : handler_(handler), breakingReturn_(breakingReturn)
{
}

bool PublicHook::Execute(AMX *amx, cell *retval) const
{
    return ((*retval = handler_(amx)) != breakingReturn_);
}

Wrapper::Wrapper() {}

Wrapper *Wrapper::GetInstance() {
    static Wrapper w;
    return &w;
}

void Wrapper::Initialize(void **ppPluginData) {
    ::pAMXFunctions = ppPluginData[PLUGIN_DATA_AMX_EXPORTS];
    logprintf = (logprintf_t)ppPluginData[PLUGIN_DATA_LOGPRINTF];

    ::amx_Register_addr = reinterpret_cast<uint32_t>((static_cast<void**>(pAMXFunctions))[PLUGIN_AMX_EXPORT_Register]);
    SetJump(reinterpret_cast<void*>(::amx_Register_addr), (void*)Register, ::amx_Register_code);

    ::amx_FindPublic_addr = reinterpret_cast<uint32_t>((static_cast<void**>(pAMXFunctions))[PLUGIN_AMX_EXPORT_FindPublic]);
    SetJump(reinterpret_cast<void*>(::amx_FindPublic_addr), (void*)FindPublic, ::amx_FindPublic_code);

    ::amx_Exec_addr = reinterpret_cast<uint32_t>((static_cast<void**>(pAMXFunctions))[PLUGIN_AMX_EXPORT_Exec]);
    SetJump(reinterpret_cast<void*>(::amx_Exec_addr), (void*)Exec, ::amx_Exec_code);

    sampgdk::InitializeCallbacks();
}

void Wrapper::SetNative(const std::string &name, AMX_NATIVE native) {
    if (!name.empty()) {
        natives_[name] = native;
    }
}

AMX_NATIVE Wrapper::GetNative(const std::string &name) const {
    std::map<std::string, AMX_NATIVE>::const_iterator it = natives_.find(name);
    if (it != natives_.end()) {
        return it->second;
    }
    return 0;
}

void Wrapper::SetPublicHook(const std::string &name, PublicHook handler) {
    publicHooks_.insert(std::make_pair(name, handler));
}

bool Wrapper::ExecutePublicHook(AMX *amx, cell *retval, const std::string &name) const {
    std::map<std::string, PublicHook>::const_iterator it = publicHooks_.find(name);
    if (it != publicHooks_.end()) {
        return it->second.Execute(amx, retval);
    }
    return true;
}

} // namespace sampgdk

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: discreteactivitybase.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: vg $ $Date: 2005-03-10 13:48:51 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SLIDESHOW_DISCRETEACTIVITYBASE_HXX
#define _SLIDESHOW_DISCRETEACTIVITYBASE_HXX

#include <activitybase.hxx>
#include <wakeupevent.hxx>

#include <vector>

namespace presentation
{
    namespace internal
    {
        /** Specialization of ActivityBase for discrete time activities.

            A discrete time activity is one where time proceeds in
            discrete steps, i.e. at given time instants.
        */
        class DiscreteActivityBase : public ActivityBase
        {
        public:
            DiscreteActivityBase( const ActivityParameters& rParms );

            /** Hook for derived classes.

                This method is called for each discrete time
                instant, with nFrame denoting the frame number
                (starting with 0)

                @param nFrame
                Current frame number.

                @param nRepeatCount
                Number of full repeats already performed
            */
            virtual void perform( sal_uInt32 nFrame, sal_uInt32 nRepeatCount ) const = 0;

            virtual void dispose();

            virtual bool perform();
            virtual void dequeued();

        protected:
            virtual void startAnimation();

            sal_uInt32 calcFrameIndex( sal_uInt32       nCurrCalls,
                                       ::std::size_t    nVectorSize ) const;

            sal_uInt32 calcRepeatCount( sal_uInt32      nCurrCalls,
                                        ::std::size_t   nVectorSize ) const;

            ::std::size_t getNumberOfKeyTimes() const { return maDiscreteTimes.size(); }

        private:
            WakeupEventSharedPtr            mpWakeupEvent;
            const ::std::vector< double >   maDiscreteTimes;
            const double                    mnSimpleDuration;
            sal_uInt32                      mnCurrPerformCalls;
        };
    }
}

#endif /* _SLIDESHOW_DISCRETEACTIVITYBASE_HXX */
<commit_msg>INTEGRATION: CWS ooo19126 (1.3.30); FILE MERGED 2005/09/05 17:41:12 rt 1.3.30.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: discreteactivitybase.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-07 20:36:53 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _SLIDESHOW_DISCRETEACTIVITYBASE_HXX
#define _SLIDESHOW_DISCRETEACTIVITYBASE_HXX

#include <activitybase.hxx>
#include <wakeupevent.hxx>

#include <vector>

namespace presentation
{
    namespace internal
    {
        /** Specialization of ActivityBase for discrete time activities.

            A discrete time activity is one where time proceeds in
            discrete steps, i.e. at given time instants.
        */
        class DiscreteActivityBase : public ActivityBase
        {
        public:
            DiscreteActivityBase( const ActivityParameters& rParms );

            /** Hook for derived classes.

                This method is called for each discrete time
                instant, with nFrame denoting the frame number
                (starting with 0)

                @param nFrame
                Current frame number.

                @param nRepeatCount
                Number of full repeats already performed
            */
            virtual void perform( sal_uInt32 nFrame, sal_uInt32 nRepeatCount ) const = 0;

            virtual void dispose();

            virtual bool perform();
            virtual void dequeued();

        protected:
            virtual void startAnimation();

            sal_uInt32 calcFrameIndex( sal_uInt32       nCurrCalls,
                                       ::std::size_t    nVectorSize ) const;

            sal_uInt32 calcRepeatCount( sal_uInt32      nCurrCalls,
                                        ::std::size_t   nVectorSize ) const;

            ::std::size_t getNumberOfKeyTimes() const { return maDiscreteTimes.size(); }

        private:
            WakeupEventSharedPtr            mpWakeupEvent;
            const ::std::vector< double >   maDiscreteTimes;
            const double                    mnSimpleDuration;
            sal_uInt32                      mnCurrPerformCalls;
        };
    }
}

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


<commit_before>// Copyright (c) 2017 Jackal Engine, MIT License.

#include "OpenGLDevice/OpenGLGraphicsPipelineState.hpp"
#include "OpenGLDevice/OpenGLShader.hpp"

// Registers an opengl error.
#define REGISTER_OPENGL_ERROR() OPENGL_CHECK_ERROR(mNativeError); \
  if (mNativeError) { \
    RegisterNativeError(); \
    return; \
  }

namespace jackal {

GLenum OpenGLGraphicsPipelineState::GetOpenGLBlendT(BlendT blend)
{
  switch (blend) {
      case BLEND_ZERO: return GL_NEVER;
      case BLEND_ONE: return GL_ONE;
      case BLEND_SRC_COLOR: return GL_SRC_COLOR;
      case BLEND_ONE_MINUS_SRC_COLOR: return GL_ONE_MINUS_SRC_COLOR;
      case BLEND_DST_COLOR: return GL_DST_COLOR;
      case BLEND_ONE_MINUS_DST_COLOR: return GL_ONE_MINUS_DST_COLOR;
      case BLEND_SRC_ALPHA: return GL_SRC_ALPHA;
      case BLEND_ONE_MINUS_SRC_ALPHA: return GL_ONE_MINUS_SRC_ALPHA;
      case BLEND_DST_ALPHA: return GL_DST_ALPHA;
      case BLEND_ONE_MINUS_DST_ALPHA: return GL_ONE_MINUS_DST_ALPHA;
      case BLEND_CONSTANT_COLOR: return GL_CONSTANT_COLOR;
      case BLEND_ONE_MINUS_CONSTANT_COLOR: return GL_ONE_MINUS_CONSTANT_COLOR;
      case BLEND_CONSTANT_ALPHA: return GL_CONSTANT_ALPHA;
      case BLEND_ONE_MINUS_CONSTANT_ALPHA: return GL_ONE_MINUS_CONSTANT_ALPHA;
      case BLEND_SRC_ALPHA_SATURATE: return GL_SRC_ALPHA_SATURATE;
      case BLEND_SRC1_COLOR: return GL_SRC1_COLOR;
      case BLEND_ONE_MINUS_SRC1_COLOR: return GL_ONE_MINUS_SRC1_COLOR;
      case BLEND_SRC1_ALPHA: return GL_SRC1_ALPHA;
      case BLEND_ONE_MINUS_SRC1_ALPHA: return GL_ONE_MINUS_SRC1_ALPHA;
      default: return GL_NEVER;
  }
}

void OpenGLGraphicsPipelineState::SetPipelineState(const
  GraphicsPipelineInfoT *info)
{
  CopyPipelineInfo(info);
}

void OpenGLGraphicsPipelineState::Update()
{
  SetUpShaderPipeline();

  // No program id? Return with errors.
  if (!mProgramId) {
    return;
  }

  if (!dirty) return;

  // Set the depth test for the pipeline.
  if (mPipelineInfo.ZBufferEnable) {
    glEnable(GL_DEPTH_TEST);
    switch (mPipelineInfo.DepthTestCompare) {
      case COMPARE_NEVER: glDepthFunc(GL_NEVER);
      case COMPARE_LESS: glDepthFunc(GL_LESS);
      case COMPARE_EQUAL: glDepthFunc(GL_EQUAL);
      case COMPARE_LESS_OR_EQUAL: glDepthFunc(GL_LEQUAL);
      case COMPARE_GREATER: glDepthFunc(GL_GREATER);
      case COMPARE_NOT_EQUAL: glDepthFunc(GL_NOTEQUAL);
      case COMPARE_GREATER_OR_EQUAL: glDepthFunc(GL_GEQUAL);
      case COMPARE_ALWAYS: glDepthFunc(GL_ALWAYS);
      default: glDepthFunc(GL_LESS);
    }
    REGISTER_OPENGL_ERROR();

  } else {
    glDisable(GL_DEPTH_TEST);
  }

  // Set the blend mode for the pipeline.
  if (mPipelineInfo.BlendEnable) {
    glEnable(GL_BLEND);
    switch (mPipelineInfo.BlendOp) {
      case BLEND_OPERATION_ADD: glBlendEquation(GL_FUNC_ADD); break;
      case BLEND_OPERATION_SUBTRACT: glBlendEquation(GL_FUNC_SUBTRACT); break;
      case BLEND_OPERATION_REVERSE_SUBTRACT: glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); break;
      case BLEND_OPERATION_MIN: glBlendEquation(GL_MIN); break;
      case BLEND_OPERATION_MAX: glBlendEquation(GL_MAX); break;
      default: glBlendEquation(GL_FUNC_ADD); break;
    }

    REGISTER_OPENGL_ERROR();

    glBlendFunc(
      GetOpenGLBlendT(mPipelineInfo.SrcBlendMode),
      GetOpenGLBlendT(mPipelineInfo.DstBlendMode)
    );

    REGISTER_OPENGL_ERROR();

    if (mNativeError) {
      RegisterNativeError();
      return;
    }

  } else {
    glDisable(GL_BLEND);
  }

  // Set Cull Face mode for the pipeline.
  if (mPipelineInfo.CullFaceEnable) {
    glEnable(GL_CULL_FACE);
    switch (mPipelineInfo.CullMode) {
      case CULL_MODE_BACK:            glCullFace(GL_BACK);            break;
      case CULL_MODE_FRONT:           glCullFace(GL_FRONT);           break;
      case CULL_MODE_FRONT_AND_BACK:  glCullFace(GL_FRONT_AND_BACK);  break;
      default:                        glCullFace(GL_BACK);            break;
    }

    REGISTER_OPENGL_ERROR();

    if (mNativeError) {
      RegisterNativeError();
      return;
    }

    switch (mPipelineInfo.FrontFace) {
      case FRONT_FACE_CLOCKWISE:          glFrontFace(GL_CW);   break;
      case FRONT_FACE_COUNTER_CLOCKWISE:  glFrontFace(GL_CCW);  break;
      default:                            glFrontFace(GL_CCW);  break;
    }

    REGISTER_OPENGL_ERROR();

    if (mNativeError) {
      RegisterNativeError();
      return;
    }
  } else {
    glDisable(GL_CULL_FACE);
  }

  if (mPipelineInfo.StencilEnable) {
    glEnable(GL_STENCIL);
  } else {
    glDisable(GL_STENCIL);
  }
}

void OpenGLGraphicsPipelineState::SetUpShaderPipeline()
{
  if (mProgramId) {
    glDeleteProgram(mProgramId);
    mProgramId = glCreateProgram();
  }

  if (!mPipelineInfo.VertexShader) {
    mLastError = RENDER_ERROR_PIPELINE_NULL_VERTEX_SHADER;
    return;
  }

  if (!mPipelineInfo.PixelShader) {
    mLastError = RENDER_ERROR_PIPELINE_NULL_PIXEL_SHADER;
  }

  OpenGLShader *shader = static_cast<OpenGLShader *>(mPipelineInfo.VertexShader);
  if (shader->Compiled()) {
    glAttachShader(mProgramId, shader->GetUID());
  }

  shader = static_cast<OpenGLShader *>(mPipelineInfo.PixelShader);
  if (shader->Compiled()) {
    glAttachShader(mProgramId, shader->GetUID());
  }

  if (mPipelineInfo.HullShader) {
    shader = static_cast<OpenGLShader *>(mPipelineInfo.HullShader);
    if (shader->Compiled()) {
      glAttachShader(mProgramId, shader->GetUID());
    }
  }

  if (mPipelineInfo.DomainShader) {
    shader = static_cast<OpenGLShader *>(mPipelineInfo.DomainShader);
    if (shader->Compiled()) {
      glAttachShader(mProgramId, shader->GetUID());
    }
  }

  if (mPipelineInfo.GeometryShader) {
    shader = static_cast<OpenGLShader *>(mPipelineInfo.GeometryShader);
    if (shader->Compiled()) {
      glAttachShader(mProgramId, shader->GetUID());
    }
  }

  // Link the program now.
  glLinkProgram(mProgramId);

  // Time to check its state.
  GLint success;
  glGetProgramiv(mProgramId, GL_LINK_STATUS, &success);
  if (!success) {
    mLastError = RENDER_ERROR_PIPELINE_SHADER_LINK_ERROR;
    glDeleteProgram(mProgramId);
    mProgramId = 0;
    return;
  }
}

void OpenGLGraphicsPipelineState::CopyPipelineInfo(const GraphicsPipelineInfoT *info)
{
  mPipelineInfo.BlendEnable = info->BlendEnable;
  mPipelineInfo.BlendOp = info->BlendOp;
  mPipelineInfo.CullFaceEnable = info->CullFaceEnable;
  mPipelineInfo.CullMode = info->CullMode;
  mPipelineInfo.DepthTestCompare = info->DepthTestCompare;
  mPipelineInfo.DstBlendMode = info->DstBlendMode;
  mPipelineInfo.SrcBlendMode = info->SrcBlendMode;
  mPipelineInfo.FrontFace = info->FrontFace;
  mPipelineInfo.ZBufferEnable = info->ZBufferEnable;
  mPipelineInfo.StencilEnable = info->StencilEnable;

  mPipelineInfo.VertexShader = info->VertexShader;
  mPipelineInfo.PixelShader = info->PixelShader;
  mPipelineInfo.HullShader = info->HullShader;
  mPipelineInfo.DomainShader = info->DomainShader;
  mPipelineInfo.GeometryShader = info->GeometryShader;
}

void OpenGLGraphicsPipelineState::RegisterNativeError()
{

}
} // jackal<commit_msg>Checking for pipeline changes<commit_after>// Copyright (c) 2017 Jackal Engine, MIT License.

#include "OpenGLDevice/OpenGLGraphicsPipelineState.hpp"
#include "OpenGLDevice/OpenGLShader.hpp"

// Registers an opengl error.
#define REGISTER_OPENGL_ERROR() OPENGL_CHECK_ERROR(mNativeError); \
  if (mNativeError) { \
    RegisterNativeError(); \
    return; \
  }

namespace jackal {

GLenum OpenGLGraphicsPipelineState::GetOpenGLBlendT(BlendT blend)
{
  switch (blend) {
      case BLEND_ZERO: return GL_NEVER;
      case BLEND_ONE: return GL_ONE;
      case BLEND_SRC_COLOR: return GL_SRC_COLOR;
      case BLEND_ONE_MINUS_SRC_COLOR: return GL_ONE_MINUS_SRC_COLOR;
      case BLEND_DST_COLOR: return GL_DST_COLOR;
      case BLEND_ONE_MINUS_DST_COLOR: return GL_ONE_MINUS_DST_COLOR;
      case BLEND_SRC_ALPHA: return GL_SRC_ALPHA;
      case BLEND_ONE_MINUS_SRC_ALPHA: return GL_ONE_MINUS_SRC_ALPHA;
      case BLEND_DST_ALPHA: return GL_DST_ALPHA;
      case BLEND_ONE_MINUS_DST_ALPHA: return GL_ONE_MINUS_DST_ALPHA;
      case BLEND_CONSTANT_COLOR: return GL_CONSTANT_COLOR;
      case BLEND_ONE_MINUS_CONSTANT_COLOR: return GL_ONE_MINUS_CONSTANT_COLOR;
      case BLEND_CONSTANT_ALPHA: return GL_CONSTANT_ALPHA;
      case BLEND_ONE_MINUS_CONSTANT_ALPHA: return GL_ONE_MINUS_CONSTANT_ALPHA;
      case BLEND_SRC_ALPHA_SATURATE: return GL_SRC_ALPHA_SATURATE;
      case BLEND_SRC1_COLOR: return GL_SRC1_COLOR;
      case BLEND_ONE_MINUS_SRC1_COLOR: return GL_ONE_MINUS_SRC1_COLOR;
      case BLEND_SRC1_ALPHA: return GL_SRC1_ALPHA;
      case BLEND_ONE_MINUS_SRC1_ALPHA: return GL_ONE_MINUS_SRC1_ALPHA;
      default: return GL_NEVER;
  }
}

void OpenGLGraphicsPipelineState::SetPipelineState(const
  GraphicsPipelineInfoT *info)
{
  CopyPipelineInfo(info);
}

void OpenGLGraphicsPipelineState::Update()
{
  SetUpShaderPipeline();

  // No program id? Return with errors.
  if (!mProgramId) {
    return;
  }

  if (!dirty) return;

  // Set the depth test for the pipeline.
  if (mPipelineInfo.ZBufferEnable) {
    glEnable(GL_DEPTH_TEST);
    switch (mPipelineInfo.DepthTestCompare) {
      case COMPARE_NEVER: glDepthFunc(GL_NEVER);
      case COMPARE_LESS: glDepthFunc(GL_LESS);
      case COMPARE_EQUAL: glDepthFunc(GL_EQUAL);
      case COMPARE_LESS_OR_EQUAL: glDepthFunc(GL_LEQUAL);
      case COMPARE_GREATER: glDepthFunc(GL_GREATER);
      case COMPARE_NOT_EQUAL: glDepthFunc(GL_NOTEQUAL);
      case COMPARE_GREATER_OR_EQUAL: glDepthFunc(GL_GEQUAL);
      case COMPARE_ALWAYS: glDepthFunc(GL_ALWAYS);
      default: glDepthFunc(GL_LESS);
    }
    REGISTER_OPENGL_ERROR();

  } else {
    glDisable(GL_DEPTH_TEST);
  }

  // Set the blend mode for the pipeline.
  if (mPipelineInfo.BlendEnable) {
    glEnable(GL_BLEND);
    switch (mPipelineInfo.BlendOp) {
      case BLEND_OPERATION_ADD: glBlendEquation(GL_FUNC_ADD); break;
      case BLEND_OPERATION_SUBTRACT: glBlendEquation(GL_FUNC_SUBTRACT); break;
      case BLEND_OPERATION_REVERSE_SUBTRACT: glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); break;
      case BLEND_OPERATION_MIN: glBlendEquation(GL_MIN); break;
      case BLEND_OPERATION_MAX: glBlendEquation(GL_MAX); break;
      default: glBlendEquation(GL_FUNC_ADD); break;
    }

    REGISTER_OPENGL_ERROR();

    glBlendFunc(
      GetOpenGLBlendT(mPipelineInfo.SrcBlendMode),
      GetOpenGLBlendT(mPipelineInfo.DstBlendMode)
    );

    REGISTER_OPENGL_ERROR();

    if (mNativeError) {
      RegisterNativeError();
      return;
    }

  } else {
    glDisable(GL_BLEND);
  }

  // Set Cull Face mode for the pipeline.
  if (mPipelineInfo.CullFaceEnable) {
    glEnable(GL_CULL_FACE);
    switch (mPipelineInfo.CullMode) {
      case CULL_MODE_BACK:            glCullFace(GL_BACK);            break;
      case CULL_MODE_FRONT:           glCullFace(GL_FRONT);           break;
      case CULL_MODE_FRONT_AND_BACK:  glCullFace(GL_FRONT_AND_BACK);  break;
      default:                        glCullFace(GL_BACK);            break;
    }

    REGISTER_OPENGL_ERROR();

    if (mNativeError) {
      RegisterNativeError();
      return;
    }

    switch (mPipelineInfo.FrontFace) {
      case FRONT_FACE_CLOCKWISE:          glFrontFace(GL_CW);   break;
      case FRONT_FACE_COUNTER_CLOCKWISE:  glFrontFace(GL_CCW);  break;
      default:                            glFrontFace(GL_CCW);  break;
    }

    REGISTER_OPENGL_ERROR();

    if (mNativeError) {
      RegisterNativeError();
      return;
    }
  } else {
    glDisable(GL_CULL_FACE);
  }

  if (mPipelineInfo.StencilEnable) {
    glEnable(GL_STENCIL);
  } else {
    glDisable(GL_STENCIL);
  }
}

void OpenGLGraphicsPipelineState::SetUpShaderPipeline()
{
  if (mProgramId) {
    glDeleteProgram(mProgramId);
    mProgramId = glCreateProgram();
  }

  if (!mPipelineInfo.VertexShader) {
    mLastError = RENDER_ERROR_PIPELINE_NULL_VERTEX_SHADER;
    return;
  }

  if (!mPipelineInfo.PixelShader) {
    mLastError = RENDER_ERROR_PIPELINE_NULL_PIXEL_SHADER;
  }

  OpenGLShader *shader = static_cast<OpenGLShader *>(mPipelineInfo.VertexShader);
  if (shader->Compiled()) {
    glAttachShader(mProgramId, shader->GetUID());
  }

  shader = static_cast<OpenGLShader *>(mPipelineInfo.PixelShader);
  if (shader->Compiled()) {
    glAttachShader(mProgramId, shader->GetUID());
  }

  if (mPipelineInfo.HullShader) {
    shader = static_cast<OpenGLShader *>(mPipelineInfo.HullShader);
    if (shader->Compiled()) {
      glAttachShader(mProgramId, shader->GetUID());
    }
  }

  if (mPipelineInfo.DomainShader) {
    shader = static_cast<OpenGLShader *>(mPipelineInfo.DomainShader);
    if (shader->Compiled()) {
      glAttachShader(mProgramId, shader->GetUID());
    }
  }

  if (mPipelineInfo.GeometryShader) {
    shader = static_cast<OpenGLShader *>(mPipelineInfo.GeometryShader);
    if (shader->Compiled()) {
      glAttachShader(mProgramId, shader->GetUID());
    }
  }

  // Link the program now.
  glLinkProgram(mProgramId);

  // Time to check its state.
  GLint success;
  glGetProgramiv(mProgramId, GL_LINK_STATUS, &success);
  if (!success) {
    mLastError = RENDER_ERROR_PIPELINE_SHADER_LINK_ERROR;
    glDeleteProgram(mProgramId);
    mProgramId = 0;
    return;
  }
}

#define CHANGE_PIPELINE(cmp1, cmp2) if (cmp1 != cmp2) dirty = true; \
  cmp1 = cmp2;

void OpenGLGraphicsPipelineState::CopyPipelineInfo(const GraphicsPipelineInfoT *info)
{
  CHANGE_PIPELINE(mPipelineInfo.BlendEnable, info->BlendEnable);
  CHANGE_PIPELINE(mPipelineInfo.BlendEnable, info->BlendEnable);
  CHANGE_PIPELINE(mPipelineInfo.BlendOp, info->BlendOp);
  CHANGE_PIPELINE(mPipelineInfo.CullFaceEnable, info->CullFaceEnable);
  CHANGE_PIPELINE(mPipelineInfo.CullMode, info->CullMode);
  CHANGE_PIPELINE(mPipelineInfo.DepthTestCompare, info->DepthTestCompare);
  CHANGE_PIPELINE(mPipelineInfo.DstBlendMode, info->DstBlendMode);
  CHANGE_PIPELINE(mPipelineInfo.SrcBlendMode, info->SrcBlendMode);
  CHANGE_PIPELINE(mPipelineInfo.FrontFace, info->FrontFace);
  CHANGE_PIPELINE(mPipelineInfo.ZBufferEnable, info->ZBufferEnable);
  CHANGE_PIPELINE(mPipelineInfo.StencilEnable, info->StencilEnable);

  CHANGE_PIPELINE(mPipelineInfo.VertexShader, info->VertexShader);
  CHANGE_PIPELINE(mPipelineInfo.PixelShader, info->PixelShader);
  CHANGE_PIPELINE(mPipelineInfo.HullShader, info->HullShader);
  CHANGE_PIPELINE(mPipelineInfo.DomainShader, info->DomainShader);
  CHANGE_PIPELINE(mPipelineInfo.GeometryShader, info->GeometryShader);
}

void OpenGLGraphicsPipelineState::RegisterNativeError()
{

}
} // jackal<|endoftext|>