Error when casting on 64bit system

Hi,
I have stumbled on a problem regarding classes derived from TGListTree and TGListTreeItemStd with overloaded functions. It might be related to the previous post [url]TEveManager, TGListTree & TEveListTreeItem but I am not sure.

I provide below a small example that works fine on my 32bit Ubuntu laptop but do not work on my 64bit gentoo desktop. The example application should print out the pointer to the item below the mouse when clicked. The 64bit system prints NULL pointer for each type of cast (for no cast also) whereas the 32bit system prints the correct pointer to the object each time.

EDIT: Forgot to mention that I tested this on ROOT version 5.26 and 5.27

[code]#include <TApplication.h>
#include <TGFrame.h>
#include <TGCanvas.h>
#include <TGListTree.h>
#include

class TestTreeItem : public TGListTreeItemStd
{
public:
TestTreeItem(const char* name){ this->Rename(name);};
};

class TestTree : public TGListTree
{
public:
TestTree( TGCanvas* p ) : TGListTree(p,kHorizontalFrame){};
TestTreeItem* GetBelowMouse1(){return dynamic_cast<TestTreeItem*>(TGListTree::GetBelowMouse());};
TestTreeItem* GetBelowMouse2(){return reinterpret_cast<TestTreeItem*>(TGListTree::GetBelowMouse());};
TestTreeItem* GetBelowMouse3(){return static_cast<TestTreeItem*>(TGListTree::GetBelowMouse());};
Bool_t HandleButton(Event_t* event){
std::cout << "No cast: " << this->GetBelowMouse() << std::endl;
std::cout << "Dynamic cast: " << this->GetBelowMouse1() << std::endl;
std::cout << "Reinterpret cast: " << this->GetBelowMouse2() << std::endl;
std::cout << "Static cast: " << this->GetBelowMouse3() << std::endl;}
};

int main(int argc, char** argv)
{
TApplication runroot(“TreeTest”,&argc,argv);
TGMainFrame* mainframe = new TGMainFrame();
TGCanvas* canvas = new TGCanvas(mainframe,100,100);
mainframe->AddFrame(canvas, new TGLayoutHints(kLHintsExpandX|kLHintsExpandY));
TestTree* tree = new TestTree(canvas);
canvas->SetContainer(tree);
tree->AddItem(NULL, new TestTreeItem(“test1”));
mainframe->MapSubwindows();
mainframe->Resize(mainframe->GetDefaultSize());
mainframe->MapWindow();
runroot.Run();
return 0;
}
[/code]

Any help is appreciated, even if it is just a bug confirmation :slight_smile:.
Thanks in advance.

Hi,

the main problem in you example is that you override the TGLIstTree::HandleButton() code which is doing all the needed button click processing. Then you use GetBelowMouse() which is not set when handling buttons. The corrected program is:

#include <TApplication.h>
#include <TGFrame.h>
#include <TGCanvas.h>
#include <TGListTree.h>
#include <iostream>

class TestTreeItem : public TGListTreeItemStd
{
  public:
    TestTreeItem(const char* name){ this->Rename(name);};
};

class TestTree : public TGListTree
{
  public:
    TestTree( TGCanvas* p ) : TGListTree(p,kHorizontalFrame){};
     Bool_t ProcessMessage(Long_t msg, Long_t parm1, Long_t parm2) {
       std::cout << "processing " << GetSelected() << std::endl;
   }
};

int main(int argc, char** argv)
{
  TApplication runroot("TreeTest",&argc,argv);
  TGMainFrame* mainframe = new TGMainFrame();
  TGCanvas* canvas = new TGCanvas(mainframe,100,100);
  mainframe->AddFrame(canvas, new TGLayoutHints(kLHintsExpandX|kLHintsExpandY));
  TestTree* tree = new TestTree(canvas);
  canvas->SetContainer(tree);
  tree->AddItem(NULL, new TestTreeItem("test1"));
  tree->Associate(tree);
  mainframe->MapSubwindows();
  mainframe->Resize(mainframe->GetDefaultSize());
  mainframe->MapWindow();
  runroot.Run();
  return 0;
}

Note the added line: tree->Associate(tree) which tells the system to send messages from the TestTree to TestTree itself. Next we added ProcessMessage() to TestTree. In the example we accept all messages and print which item was selected. More detailed processing can be done using GET_MSG() and GET_SUBMSG() to get the messages described in the TGListTree.h file. See also the $ROOTSYS/test/guitest.cxx program.

Cheers, Fons.

Thanks for the explanation, makes kind of sense I guess. I will try to rewrite the event handling.

But if I do it the wrong way, how can it work perfectly on my 32 bit system?

It could have worked semi-perfect on your 32-bit system, for example if you first double-clicked on the item, so it became selected and the below got set.

Cheers, Fons.

I think I must take back that I thought it made sense. It did initially but then I again examined the source code of TGListTree and found that TGListTree::fBelowMouse is set by TGListTree::HandleMotion(Event_t*) (which I do not overload). So every time a motion event is processed the fBelowMouse is updated which I later can use i HandleButton(Event_t* event) since GetBelowMouse() only returns fBelowMouse?

Am I being stupid and missing some important aspect of the ROOT event handling?

(Also, in my real code I call TGListTree::HandleButton(Event_t*) from my own HandleButton(Event*) so all original processing is still made.)

In principle HandleButton is not to be used to process events, either use ProcessMessage() or use signal/slots and connect to the “Clicked()” signal emitted by the TGListTree. You should modify HandleButton() if you want to customize when/how the Button event is to be generated.

Cheers, Fons.

Usually I connect a slot to the “ProcessedEvent(Event_t*)” signal but in this case I really need to overload HandleButton since I need some code to be executed right before TGListTree::HandleButton and some right after.

But anyway, I still fail to see how my code could effect TGListTree::HandleMotion since I do not touch neither TGListTree::HandleMotion nor TGFrame::HandleEvent (which distributes the events to the specific handlers).

Like I said no problem over riding HandleButton(), but just don’t use it as event handler.

– Fons

Ok, thank you for your suggestions. I will continue investigate the GetBelowMouse() problem which I still don’t understand.