void ExperienceAssociationResponder::sendResult( const LLSD& experience )
{
    mCallback(experience);
    unref();
}
void w_env_select::select_item(dialog *parent)
{
	// Find available files
	vector<FileSpecifier> files;
	if (type == _typecode_theme) {

		// Theme, find by theme script
		FindThemes finder(files);
		vector<DirectorySpecifier>::const_iterator i = data_search_path.begin(), end = data_search_path.end();
		while (i != end) {
			FileSpecifier dir = *i + "Themes";
			finder.Find(dir, WILDCARD_TYPE);
			i++;
		}

	} else {

		// Map/phyics/shapes/sounds, find by type
		FindAllFiles finder(files);
		vector<DirectorySpecifier>::const_iterator i = data_search_path.begin(), end = data_search_path.end();
		while (i != end) {
			FileSpecifier dir = *i;
			finder.Find(dir, type);
			i++;
		}
	}

	// Create structured list of files
	vector<env_item> items;
	vector<FileSpecifier>::const_iterator i = files.begin(), end = files.end();
	string last_base;
	int indent_level = 0;
	for (i = files.begin(); i != end; i++) {
		string base, part;
		i->SplitPath(base, part);
		if (base != last_base) {

			// New directory
			FileSpecifier base_spec = base;
#ifdef __MACOS__
			char name[256];
			base_spec.GetName(name);
			if (name[0] != '\0') {
#endif
				// Subdirectory, insert name as unselectable item, put items on indentation level 1
				items.push_back(env_item(base_spec, 0, false));
				indent_level = 1;
#ifdef __MACOS__
			} else {

				// Top-level directory, put items on indentation level 0
				indent_level = 0;
			}
#endif
			last_base = base;
		}
		items.push_back(env_item(*i, indent_level, true));
	}

	// Create dialog
	dialog d;
	vertical_placer *placer = new vertical_placer;
	
	placer->dual_add(new w_title(menu_title), d);
	placer->add(new w_spacer(), true);
	w_env_list *list_w = new w_env_list(items, item.GetPath(), &d);
	placer->dual_add(list_w, d);
	placer->add(new w_spacer(), true);
	placer->dual_add(new w_button("キャンセル", dialog_cancel, &d), d);

	d.activate_widget(list_w);
	d.set_widget_placer(placer);

	// Clear screen
	clear_screen();

	// Run dialog
	if (d.run() == 0) { // Accepted
		if (items.size())
			set_path(items[list_w->get_selection()].spec.GetPath());

        if(mCallback)
            mCallback(this);
	}
}
Beispiel #3
0
	void update()
	{
		mCallback();
	}
void
TraceCallbackFunc::Trace(JS::Heap<JSObject*>* aPtr, const char* aName,
                         void* aClosure) const
{
  mCallback(JS::GCCellPtr(aPtr->get()), aName, aClosure);
}
void LiveAssetPair::notify()
{
    mCallback( ci::app::loadAsset( mRelativePath.first ), ci::app::loadAsset( mRelativePath.second ) );
}
Beispiel #6
0
void LiveAssetSingle::reload()
{
    mCallback( loadFile( mFilePath ) );
}
Beispiel #7
0
void LLFloaterPay::give(S32 amount)
{
	if(mCallback)
	{
		// if the amount is 0, that menas that we should use the
		// text field.
		if(amount == 0)
		{
			amount = atoi(childGetText("amount").c_str());
		}
		sLastAmount = amount;

		// Try to pay an object.
		if (mTargetIsObject)
		{
			LLViewerObject* dest_object = gObjectList.findObject(mTargetUUID);
			if(dest_object)
			{
				LLViewerRegion* region = dest_object->getRegion();
				if (region)
				{
					// Find the name of the root object
					LLSelectNode* node = mObjectSelection->getFirstRootNode();
					std::string object_name;
					if (node)
					{
						object_name = node->mName;
					}
					S32 tx_type = TRANS_PAY_OBJECT;
					if(dest_object->isAvatar()) tx_type = TRANS_GIFT;
					mCallback(mTargetUUID, region, amount, FALSE, tx_type, object_name);
					mObjectSelection = NULL;

					// request the object owner in order to check if the owner needs to be unmuted
					LLSelectMgr::registerObjectPropertiesFamilyRequest(mTargetUUID);
 					LLMessageSystem* msg = gMessageSystem;
					msg->newMessageFast(_PREHASH_RequestObjectPropertiesFamily);
					msg->nextBlockFast(_PREHASH_AgentData);
					msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
					msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
					msg->nextBlockFast(_PREHASH_ObjectData);
					msg->addU32Fast(_PREHASH_RequestFlags, OBJECT_PAY_REQUEST );
					msg->addUUIDFast(_PREHASH_ObjectID, 	mTargetUUID);
					msg->sendReliable( region->getHost() );
				}
			}
		}
		else
		{
			// Custom message typed in by the user.
			std::string desc = LLStringUtil::null;
			if (!childGetText("message").empty())
			{
				desc = childGetText("message");
			}

			// just transfer the L$
			mCallback(mTargetUUID, gAgent.getRegion(), amount, mTargetIsGroup, TRANS_GIFT, desc);

			// check if the payee needs to be unmuted
			LLMuteList::getInstance()->autoRemove(mTargetUUID, LLMuteList::AR_MONEY);
		}
	}
}
Beispiel #8
0
void Button::callback()
{
	mCallback();
}
Beispiel #9
0
void Checkbox::callback()
{
	mIsChecked = mCallback();
}
Beispiel #10
0
ColorWheel::Region ColorWheel::adjustPosition(const ivec2 &p, Region consideredRegions)
{

    float x = p.x - mPos.x, y = p.y - mPos.y, w = mSize.x, h = mSize.y;

    float cx = w*0.5f;
    float cy = h*0.5f;
    float r1 = (w < h ? w : h) * 0.5f - 5.0f;
    float r0 = r1 * .75f;

    x -= cx;
    y -= cy;

    float mr = glm::sqrt(x*x + y*y);

    if ((consideredRegions & OuterCircle) &&
            ((mr >= r0 && mr <= r1) || (consideredRegions == OuterCircle))) {
        if (!(consideredRegions & OuterCircle))
            return None;
        mHue = std::atan(y / x);
        if (x < 0)
            mHue += NVG_PI;
        mHue /= 2 * NVG_PI;

        if (mCallback)
            mCallback(color());

        return OuterCircle;
    }

    float r = r0 - 6;

    float hueAngle = float(NVG_PI * 2) * mHue;
    const float angle = float(NVG_PI * 120 / 180);
    glm::vec2 a(r * glm::cos(hueAngle + angle), r * glm::sin(hueAngle + angle));
    glm::vec2 b(r * glm::cos(hueAngle - angle), r * glm::sin(hueAngle - angle));
    glm::vec2 c(r * glm::cos(hueAngle), r * glm::sin(hueAngle));

    vec3 bary = calcBarycentric(vec2(x, y), a, b, c);

    float l0 = bary[0], l1 = bary[1], l2 = bary[2];
    bool triangleTest = l0 >= 0 && l0 <= 1.f && l1 >= 0.f && l1 <= 1.f && l2 >= 0.f && l2 <= 1.f;

    if ((consideredRegions & InnerTriangle) &&
            (triangleTest || consideredRegions == InnerTriangle)) {
        if (!(consideredRegions & InnerTriangle))
            return None;
        l0 = std::min(std::max(0.f, l0), 1.f);
        l1 = std::min(std::max(0.f, l1), 1.f);
        l2 = std::min(std::max(0.f, l2), 1.f);
        float sum = l0 + l1 + l2;
        l0 /= sum;
        l1 /= sum;
        mWhite = l0;
        mBlack = l1;
        if (mCallback)
            mCallback(color());
        return InnerTriangle;
    }
    return None;
}
Beispiel #11
0
 inline void notifyCaller(std::tr1::shared_ptr<TransferRequest> from) {
     std::tr1::shared_ptr<MetadataRequest> fromC =
             std::tr1::static_pointer_cast<MetadataRequest, TransferRequest>(from);
     mCallback(fromC, fromC->mRemoteFileMetadata);
 }
void AnimatedSprite::executeCallback()
{
    mCallback();
}
Beispiel #13
0
 void Button::onClick()
 {
     if(mCallback) { mCallback(); }
 }
void MyoThread::run()
{
    //get start time
    double timeStart = myo::GetTime();
    double timePush  = myo::GetTime();
    //alloc for ptrs for smooth
    auto emgPtrArray = new std::array< int8_t , 8UL >*[mFlags.mReps] ;
    //thread loop
    while(mLoop)
    {
        //hub
        mMyoDevice->unlock(myo::Myo::unlockHold);
        mMyoHub->run(1000/20);
        //modes
        switch (mFlags.mMode)
        {
            case DataFlags::GESTURE_MODE:
            {
                if((myo::GetTime()-timePush) >= mFlags.mDeltaTime)
                {
                    //put value
                    mInputs.push_back(mMyoListener.getInput());
                    mInputs[mInputs.size()-1].setTime(myo::GetTime()-timeStart);
                    //update push time
                    timePush = myo::GetTime();
                }
                
                //... by time...
                //if((myo::GetTime()-timeStart) >= mFlags.mTimePerGesture)
                //or... by reps
                if (mInputs.size() >= mFlags.mReps)
                {
                    //set ptrs
                    for (size_t i=0; i!= mFlags.mReps; ++i)
                    {
                        emgPtrArray[i] = &mInputs[i].getEmg();
                    }
                    //applay
                    mFlags.applayEmgFilter(emgPtrArray, mFlags.mReps);
                    //put input 
                    mCallback(mInputs,mFlags,mMutex);
                    mInputs.clear();
                    //restart
                    timeStart = myo::GetTime();
                }
            }
            break;
            case DataFlags::SEMPLE_MODE:
            {
                //add all inputs
                mInputs.push_back(mMyoListener.getInput());
                mInputs[mInputs.size()-1].setTime(myo::GetTime()-timeStart);
                //reps
                if (mInputs.size() >= mFlags.mReps)
                {
                    mCallback(mInputs,mFlags,mMutex);
                    mInputs.clear();
                }
            }
            default:break;
        }
    }
    //dealloc
    delete [] emgPtrArray;
}
Beispiel #15
0
ColorWheel::Region ColorWheel::adjustPosition(const Vector2i &p, Region consideredRegions) {
    float x = p.x() - mPos.x(),
          y = p.y() - mPos.y(),
          w = mSize.x(),
          h = mSize.y();

    float cx = w*0.5f;
    float cy = h*0.5f;
    float r1 = (w < h ? w : h) * 0.5f - 5.0f;
    float r0 = r1 * .75f;

    x -= cx;
    y -= cy;

    float mr = std::sqrt(x*x + y*y);

    if ((consideredRegions & OuterCircle) &&
        ((mr >= r0 && mr <= r1) || (consideredRegions == OuterCircle))) {
        if (!(consideredRegions & OuterCircle))
            return None;
        mHue = std::atan(y / x);
        if (x < 0)
            mHue += NVG_PI;
        mHue /= 2*NVG_PI;

        if (mCallback)
            mCallback(color());

        return OuterCircle;
    }

    float r = r0 - 6;

    float ax = std::cos( 120.0f/180.0f*NVG_PI) * r;
    float ay = std::sin( 120.0f/180.0f*NVG_PI) * r;
    float bx = std::cos(-120.0f/180.0f*NVG_PI) * r;
    float by = std::sin(-120.0f/180.0f*NVG_PI) * r;

    typedef Eigen::Matrix<float,2,2>        Matrix2f;

    Eigen::Matrix<float, 2, 3> triangle;
    triangle << ax,bx,r,
                ay,by,0;
    triangle = Eigen::Rotation2D<float>(mHue * 2 * NVG_PI).matrix() * triangle;

    Matrix2f T;
    T << triangle(0,0) - triangle(0,2), triangle(0,1) - triangle(0,2),
         triangle(1,0) - triangle(1,2), triangle(1,1) - triangle(1,2);
    Vector2f pos { x - triangle(0,2), y - triangle(1,2) };

    Vector2f bary = T.colPivHouseholderQr().solve(pos);
    float l0 = bary[0], l1 = bary[1], l2 = 1 - l0 - l1;
    bool triangleTest = l0 >= 0 && l0 <= 1.f && l1 >= 0.f && l1 <= 1.f &&
                        l2 >= 0.f && l2 <= 1.f;

    if ((consideredRegions & InnerTriangle) &&
        (triangleTest || consideredRegions == InnerTriangle)) {
        if (!(consideredRegions & InnerTriangle))
            return None;
        l0 = std::min(std::max(0.f, l0), 1.f);
        l1 = std::min(std::max(0.f, l1), 1.f);
        l2 = std::min(std::max(0.f, l2), 1.f);
        float sum = l0 + l1 + l2;
        l0 /= sum;
        l1 /= sum;
        mWhite = l0;
        mBlack = l1;
        if (mCallback)
            mCallback(color());
        return InnerTriangle;
    }

    return None;
}
int SimplePollerCallback::handleEvent(int fd, int events, void* data) {
    return mCallback(fd, events, data);
}
 /** \see ThreadSafeQueue::pushMultiple. */
 void pushMultiple(const std::deque<T> &values) {
     int32 nelements = values.size();
     int32 new_size = mQueue.pushMultiple(values);
     if (new_size == nelements)
         mCallback();
 }
void GUI::SlideBar::mouseAt(int x, int y) {
    if ((!mMouseClickHolded && !contains(x,y)) || (mMouseClickHolded && !contains(x,getPosition().y+mHeight/2.f))) return;
    float division = (x-getPosition().x)/(mLength/((float) mSteps-1));
    mCurrentStep = (division - (int) division > 0.5 ? (int) division + 1 : (int) division);
    mCallback(mCurrentStep);
}
Beispiel #19
0
void LiveAssetDouble::reload()
{
    mCallback( loadFile( mFilePath1 ), loadFile( mFilePath2 ) );
}
void
TraceCallbackFunc::Trace(JS::Heap<JSScript*>* p, const char* name, void* closure) const
{
  mCallback(p->get(), name, closure);
}
 void FunctorSelectionListener::valueChanged(const SelectionEvent& selectionEvent) {
     if (mCallback)
     {
         mCallback(selectionEvent);
     }
 }
void
TraceCallbackFunc::Trace(JS::Heap<JS::Value>* p, const char* name, void* closure) const
{
  mCallback(JSVAL_TO_TRACEABLE(p->get()), name, closure);
}
void LiveAsset::notify()
{
    mCallback( ci::app::loadAsset( mRelativePath ) );
}
void
TraceCallbackFunc::Trace(JS::TenuredHeap<JSObject*>* p, const char* name, void* closure) const
{
  mCallback(*p, name, closure);
}
SimpleTiledLayerTile
SimpleTiledLayerBuffer::ValidateTile(SimpleTiledLayerTile aTile,
                                     const nsIntPoint& aTileOrigin,
                                     const nsIntRegion& aDirtyRegion)
{
  PROFILER_LABEL("SimpleTiledLayerBuffer", "ValidateTile");
  static gfx::IntSize kTileSize(gfxPrefs::LayersTileWidth(), gfxPrefs::LayersTileHeight());

  gfx::SurfaceFormat tileFormat = gfxPlatform::GetPlatform()->Optimal2DFormatForContent(GetContentType());

  // if this is true, we're using a separate buffer to do our drawing first
  bool doBufferedDrawing = true;
  bool fullPaint = false;

  RefPtr<TextureClient> textureClient = mManager->GetSimpleTileTexturePool(tileFormat)->GetTextureClientWithAutoRecycle();

  if (!textureClient) {
    NS_WARNING("TextureClient allocation failed");
    return SimpleTiledLayerTile();
  }

  if (!textureClient->Lock(OPEN_READ_WRITE)) {
    NS_WARNING("TextureClient lock failed");
    return SimpleTiledLayerTile();
  }

  if (!textureClient->CanExposeDrawTarget()) {
    doBufferedDrawing = false;
  }

  RefPtr<DrawTarget> drawTarget;

  unsigned char *bufferData = nullptr;

  // these are set/updated differently based on doBufferedDrawing
  nsIntRect drawBounds;
  nsIntRegion drawRegion;
  nsIntRegion invalidateRegion;

  RefPtr<DrawTarget> srcDT;
  uint8_t* srcData = nullptr;
  int32_t srcStride = 0;
  gfx::IntSize srcSize;
  gfx::SurfaceFormat srcFormat = gfx::SurfaceFormat::UNKNOWN;

  if (doBufferedDrawing) {
    // try to directly access the pixels of the TextureClient
    srcDT = textureClient->GetAsDrawTarget();
    if (srcDT->LockBits(&srcData, &srcSize, &srcStride, &srcFormat)) {
      if (!aTile.mCachedBuffer) {
        aTile.mCachedBuffer = SharedBuffer::Create(srcStride * srcSize.height);
        fullPaint = true;
      }
      bufferData = (unsigned char*) aTile.mCachedBuffer->Data();

      drawTarget = gfxPlatform::GetPlatform()->CreateDrawTargetForData(bufferData,
                                                                       kTileSize,
                                                                       srcStride,
                                                                       tileFormat);

      if (fullPaint) {
        drawBounds = nsIntRect(aTileOrigin.x, aTileOrigin.y, GetScaledTileSize().width, GetScaledTileSize().height);
        drawRegion = nsIntRegion(drawBounds);
      } else {
        drawBounds = aDirtyRegion.GetBounds();
        drawRegion = nsIntRegion(drawBounds);
        if (GetContentType() == gfxContentType::COLOR_ALPHA)
          drawTarget->ClearRect(Rect(drawBounds.x - aTileOrigin.x, drawBounds.y - aTileOrigin.y,
                                     drawBounds.width, drawBounds.height));
      }
    } else {
      // failed to obtain the client as an ImageSurface
      doBufferedDrawing = false;
    }
  }

  // this might get set above if we couldn't extract out a buffer
  if (!doBufferedDrawing) {
    drawTarget = textureClient->GetAsDrawTarget();

    fullPaint = true;
    drawBounds = nsIntRect(aTileOrigin.x, aTileOrigin.y, GetScaledTileSize().width, GetScaledTileSize().height);
    drawRegion = nsIntRegion(drawBounds);

    if (GetContentType() == gfxContentType::COLOR_ALPHA)
      drawTarget->ClearRect(Rect(0, 0, drawBounds.width, drawBounds.height));
  }

  // do the drawing
  RefPtr<gfxContext> ctxt = new gfxContext(drawTarget);

  ctxt->Scale(mResolution, mResolution);
  ctxt->Translate(gfxPoint(-aTileOrigin.x, -aTileOrigin.y));

  mCallback(mThebesLayer, ctxt,
            drawRegion,
            fullPaint ? DrawRegionClip::CLIP_NONE : DrawRegionClip::DRAW_SNAPPED, // XXX DRAW or DRAW_SNAPPED?
            invalidateRegion,
            mCallbackData);

  ctxt = nullptr;

  if (doBufferedDrawing) {
    memcpy(srcData, bufferData, srcSize.height * srcStride);
    bufferData = nullptr;
    srcDT->ReleaseBits(srcData);
    srcDT = nullptr;
  }

  drawTarget = nullptr;
  textureClient->Unlock();

  if (!mCompositableClient->AddTextureClient(textureClient)) {
    NS_WARNING("Failed to add tile TextureClient [simple]");
    return SimpleTiledLayerTile();
  }

  // aTile.mCachedBuffer was set earlier
  aTile.mTileBuffer = textureClient;
  aTile.mManager = mManager;
  aTile.mLastUpdate = TimeStamp::Now();

  return aTile;
}
void
TraceCallbackFunc::Trace(JS::Heap<JSFunction*>* p, const char* name, void* closure) const
{
  mCallback(*p, name, closure);
}
Beispiel #27
0
 void Callback(uint32_t aFlags) {
     if (mCallback != NULL) {
         mCallback(aFlags, mContext);
     }
 }
//loop
void MyoManager::run()
{
    try
    {
        //alloc
        mMyoHub = new myo::Hub("com.weka.genfiles");
    }
    catch ( const std::runtime_error&  error )
    {
        mMyoHub = nullptr;
    }
    //max try count
    const ushort mac_count_try = 5;
    //wait connection
    for(ushort count_try = 0;
            count_try != mac_count_try && (mLoop && mMyoHub && !mMyo);
            ++count_try)
    {
        mMyo    = mMyoHub->waitForMyo(1000);
    }
    //if connected
    if(mMyo)
    {
        mMyo->setStreamEmg(myo::Myo::streamEmgEnabled);
        mMyoHub->addListener(&mListener);
        mMyoHub->setLockingPolicy(myo::Hub::lockingPolicyNone);

#ifndef USE_SIGNALS
        if(mCBConnection) mCBConnection(true);
#else
        emit connectionStatusChange(true);
#endif

        while(mLoop)
        {
            //send all message
            mMyoHub->run(MyoData::msupadate);
            //if not connected stop.
            if(!mListener.mConnected) mLoop = false;
            //rec
            if(mRecording)
            {
                //lock
                mMutex.lock();
                //compute diff
                double recTime = (myo::GetTime()-mTime) / 1000.0;
                //append
                mDatas.append(mListener.mRaw);
                //set time
                mDatas[mDatas.size()-1].setTime(recTime);
                //callback
                if(mDatas.size()==mSizeNext)
                {
                    mCallback(mMutex,mDatas);
                    //next
                    mSizeNext=mSizeData+mDatas.size();
                }
                //unlock
                mMutex.unlock();
            }
        }
    }
    //loop is stopped
    mLoop = false;
    //is disconected
    mListener.mConnected = false;
    //myo last
    mMyo = nullptr;
    //dealloc
    if(mMyoHub) delete mMyoHub;
    //callback
#ifndef USE_SIGNALS
    if(mCBConnection) mCBConnection(false);
#else
    emit connectionStatusChange(false);
#endif
}
void MyoThread::run()
{
    //get start time
    double timeStart = myo::GetTime();
    double timePush  = myo::GetTime();
    //alloc for ptrs for smooth
    auto emgPtrArray = new std::array< int8_t , 8UL >*[mFlags.mReps] ;
    //update usleap
    unsigned int usfactor = 1000/std::max((unsigned int)mUpdate,(unsigned int)2);
    //thread loop
    while(mLoop)
    {
        //wait
        usleep(usfactor * 1000);
        //modes
        switch (mFlags.mMode)
        {
            case DataFlags::GESTURE_MODE:
            {
                if((myo::GetTime()-timePush) >= mFlags.mDeltaTime)
                {
                    //put value
                    mInputs.push_back(myo::getMyoDataCollector().getInput());
                    mInputs[mInputs.size()-1].setTime(myo::GetTime()-timeStart);
                    //update push time
                    timePush = myo::GetTime();
                }
                
                //... by time...
                //if((myo::GetTime()-timeStart) >= mFlags.mTimePerGesture)
                //or... by reps
                if (mInputs.size() >= mFlags.mReps)
                {
                    //set ptrs
                    for (size_t i=0; i!= mFlags.mReps; ++i)
                    {
                        emgPtrArray[i] = &mInputs[i].getEmg();
                    }
                    //applay
                    mFlags.applayEmgFilter(emgPtrArray, mFlags.mReps);
                    //put input 
                    mCallback(mInputs,mFlags,mMutex);
                    mInputs.clear();
                    //restart
                    timeStart = myo::GetTime();
                }
            }
            break;
            case DataFlags::SAMPLE_MODE:
            {
                //add all inputs
                mInputs.push_back(myo::getMyoDataCollector().getInput());
                mInputs[mInputs.size()-1].setTime(myo::GetTime()-timeStart);
                //reps
                if (mInputs.size() >= mFlags.mReps)
                {
                    mCallback(mInputs,mFlags,mMutex);
                    mInputs.clear();
                }
            }
            default:break;
        }
    }
    //dealloc
    delete [] emgPtrArray;
}
NS_IMETHODIMP
nsCategoryObserver::Observe(nsISupports* aSubject, const char* aTopic,
                            const char16_t* aData)
{
  MOZ_ASSERT(NS_IsMainThread());

  if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
    mHash.Clear();
    RemoveObservers();

    return NS_OK;
  }

  if (!aData ||
      !nsDependentString(aData).Equals(NS_ConvertASCIItoUTF16(mCategory))) {
    return NS_OK;
  }

  nsAutoCString str;
  nsCOMPtr<nsISupportsCString> strWrapper(do_QueryInterface(aSubject));
  if (strWrapper) {
    strWrapper->GetData(str);
  }

  if (strcmp(aTopic, NS_XPCOM_CATEGORY_ENTRY_ADDED_OBSERVER_ID) == 0) {
    // We may get an add notification even when we already have an entry. This
    // is due to the notification happening asynchronously, so if the entry gets
    // added and an nsCategoryObserver gets instantiated before events get
    // processed, we'd get the notification for an existing entry.
    // Do nothing in that case.
    if (mHash.GetWeak(str)) {
      return NS_OK;
    }

    nsCOMPtr<nsICategoryManager> catMan =
      do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
    if (!catMan) {
      return NS_OK;
    }

    nsCString entryValue;
    catMan->GetCategoryEntry(mCategory.get(),
                             str.get(),
                             getter_Copies(entryValue));

    nsCOMPtr<nsISupports> service = do_GetService(entryValue.get());

    if (service) {
      mHash.Put(str, service);
    }
    if (mCallback) {
      mCallback(mClosure);
    }
  } else if (strcmp(aTopic, NS_XPCOM_CATEGORY_ENTRY_REMOVED_OBSERVER_ID) == 0) {
    mHash.Remove(str);
    if (mCallback) {
      mCallback(mClosure);
    }
  } else if (strcmp(aTopic, NS_XPCOM_CATEGORY_CLEARED_OBSERVER_ID) == 0) {
    mHash.Clear();
    if (mCallback) {
      mCallback(mClosure);
    }
  }
  return NS_OK;
}