[won't fix] right-clicking & context menus

You discovered a bug in the engine, and you are sure that it is not a problem of your code? Just post it in here. Please read the bug posting guidelines first.
Post Reply
squisher
Competition winner
Posts: 91
Joined: Sat May 17, 2008 2:23 am
Contact:

[won't fix] right-clicking & context menus

Post by squisher »

Not entirely a bug, but if a user right-clicks outside of a context menu it should close the menu (it currently doesn't). (Compare to right-clicking different spots on your desktop)

To resolve this I changed

Code: Select all

                         case EMIE_LMOUSE_LEFT_UP:


to

Code: Select all

                        case EMIE_RMOUSE_LEFT_UP:
                        case EMIE_LMOUSE_LEFT_UP:
In my own copy of IrrLicht 1.6.1, around line 253 in CGUIContextMenu.cpp. Any chance you could include this in future releases?
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Post by CuteAlien »

Thanks, that sounds useful. I have to test it some more (menu changes tend to often break other situations when you change one place), but in a quick test I just did I also feel that it should be changed. And I found another minor menu problem in the last days anyway which also should be fixed (windows lose the active state when menus are clicked).
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
squisher
Competition winner
Posts: 91
Joined: Sat May 17, 2008 2:23 am
Contact:

Post by squisher »

Thanks..

I submitted this to the tracker.. https://sourceforge.net/tracker/?func=d ... tid=540676
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Post by CuteAlien »

Finally found some time for this problem, but I'm sorry - after some experimenting and testing I decided to keep the current behavior.

I tested several applications and yes - it often is implemented to close the menu on right-click (some on right-down, some on right-up), although not throughout (qt doesn't seem to do it, at least not in kde3 applications).

Unfortunately it doesn't work so well in Irrlicht. The problem is that this menu is very often opened with a right-button-down-click. And this would close such menus immediately again - which obviously isn't wanted. So the solution above won't do it. I tried a few other tricks to get that, but had no luck.

A solution around it might be if the element was not focused before the right-button-click and ignore the click in that case. But tricky because by the time the gui gets this click the element usually already has the focus. So this would have to be implemented outside the element, which again gets hard because we don't have necessarily just a single context menu in Irrlicht.

So for now it looks to me like we can't close menus on right-click. And as it's not that hard to implement this behavior in the application, I guess we can live with it.

Here's my menu-test application in case it gives you more ideas:

Code: Select all

#include <irrlicht.h>
#include <iostream>

using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;

#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib")
#endif

enum 
{
	E_RIGHT_CLICK_MENUES = 1,
	E_LEFT_CLICK_AREA,
	E_LEFT_CLICK_AREA_OPEN,
};

struct SAppContext
{
	IrrlichtDevice * Device;
	gui::IGUIEnvironment* Environment;
	gui::IGUIStaticText* LeftClickArea;
	gui::IGUIStaticText* LeftClickAreaOpen;
	gui::IGUIStaticText* StatusBar;
	gui::IGUIButton * CreateRightClickMenues;
};

void FillMenu( gui::IGUIContextMenu* menu )
{
	menu->addItem(L"top1", -1, true, true);
	menu->addItem(L"top2", -1, true, true);
	menu->addItem(L"no sub", -1, true, false);
	IGUIContextMenu* submenu = menu->getSubMenu(0);
	if ( submenu )
	{
        submenu->addItem(L"item1", -1);
        submenu->addSeparator();
        submenu->addItem(L"item2", -1);
        submenu->addItem(L"checked", -1, true, false, true);
        submenu->addItem(L"sub1", -1, true, true, false );
        submenu->addItem(L"sub2", -1, true, true, false );
		submenu->addItem(L"disabled", -1, false, false, false);
		submenu->addItem(L"autochecked", -1, true, false, false, true);
		submenu->insertItem(3, L"inserted at 3", -1);
	}
	IGUIContextMenu* subsubmenu = submenu->getSubMenu(4);
	if ( subsubmenu )
	{
        subsubmenu->addItem(L"subitemA", -1);
        subsubmenu->addItem(L"subitemB", -1);
	}
	subsubmenu = submenu->getSubMenu(5);
	if ( subsubmenu )
	{
		subsubmenu->addItem(L"subitemC", -1);
		subsubmenu->addItem(L"subitemD", -1);
	}
	
	submenu = menu->getSubMenu(1);
	if ( submenu )
	{
        submenu->addItem(L"item", -1);
	}	
}

class MyEventReceiver : public IEventReceiver
{
public:
	MyEventReceiver(SAppContext & context) : Context(context), ContextMenu(0) { }
	
	void ShowContextMenu(irr::s32 x, irr::s32 y, bool keepOpen)
	{
		core::rect<s32> rect(x, y, x+50, y+50);
		ContextMenu = Context.Environment->addContextMenu (rect);
		if ( keepOpen )
			ContextMenu->setCloseHandling(ECMC_IGNORE);
		FillMenu(ContextMenu);
	};

	virtual bool OnEvent(const SEvent& event)
	{
		if (event.EventType == EET_MOUSE_INPUT_EVENT )
		{
			if ( event.MouseInput.Event == EMIE_RMOUSE_PRESSED_DOWN )
			{
				if ( 	!Context.LeftClickArea->isPointInside( core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y) ) 
				     && !Context.LeftClickAreaOpen->isPointInside( core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y) ) 
				     && Context.CreateRightClickMenues->isPressed()
				   )
				{
					ShowContextMenu(event.MouseInput.X, event.MouseInput.Y, false);
				}
			}
			if ( event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP )
			{
				Context.StatusBar->setText(L"");
				if ( Context.LeftClickArea->isPointInside( core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y) ) )
				{
					ShowContextMenu(event.MouseInput.X, event.MouseInput.Y, false);
					return true;
				}
				if ( Context.LeftClickAreaOpen->isPointInside( core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y) ) )
				{
					ShowContextMenu(event.MouseInput.X, event.MouseInput.Y, true);
					return true;
				}
			}
		}
		if (event.EventType == EET_GUI_EVENT)
		{
			switch(event.GUIEvent.EventType)
			{
			case EGET_MENU_ITEM_SELECTED:
			{
				IGUIContextMenu * menu = static_cast<IGUIContextMenu*>(event.GUIEvent.Caller);
				s32 idx = menu->getSelectedItem();
				if ( idx >= 0 )
					Context.StatusBar->setText(menu->getItemText(idx));
				else
					Context.StatusBar->setText(L"selected event, but no item selected - should never happen.");
				break;
			}
			default:
				break;
			}
		}

		return false;
	}

private:
	SAppContext & Context;
	gui::IGUIContextMenu* ContextMenu;
};


int main()
{
	video::E_DRIVER_TYPE driverType = video::EDT_OPENGL;
	//IrrlichtDevice * device = createDevice(driverType, core::dimension2d<s32>(640, 480));	// <= irrlicht 1.5
	IrrlichtDevice * device = createDevice(driverType, core::dimension2d<u32>(640, 480));	// >= irrlicht 1.6
	if (device == 0)
		return 1; // could not create selected driver.

	video::IVideoDriver* driver = device->getVideoDriver();
	IGUIEnvironment* env = device->getGUIEnvironment();
	
	SAppContext context;
	context.Device = device;
	context.Environment = env;
	
	// menu bar in main window
	gui::IGUIContextMenu* menuBar = env->addMenu (0, -1);
	FillMenu(menuBar);
	
	// some dummy button below menu to see if mouse-clicks are correctly eaten by the menu
	core::rect<s32> rectBtn(0, 15, 150, 90);
	context.CreateRightClickMenues = env->addButton (rectBtn, 0, E_RIGHT_CLICK_MENUES, L"right-click context menu");
	context.CreateRightClickMenues->setIsPushButton(true);
	
	// menu bar in sub-window
	core::rect<s32> rectWnd(10, 100, 300, 200);
	IGUIWindow * wnd = env->addWindow (rectWnd, false, L"window", NULL, -1);
	gui::IGUIContextMenu* menuBar2 = env->addMenu (wnd, -1);
	FillMenu(menuBar2);
		
	core::rect<s32> rectStatic(10, 359, 150, 400);
	context.LeftClickArea = env->addStaticText (L"left click menu", rectStatic, true, true, 0, E_LEFT_CLICK_AREA, true);
	
	core::rect<s32> rectStaticOpen(160, 359, 300, 400);
	context.LeftClickAreaOpen = env->addStaticText (L"left click menu staying open", rectStaticOpen, true, true, 0, E_LEFT_CLICK_AREA_OPEN, true);
	
	core::rect<s32> rectStatusBar(0, 450, 640, 480);
	context.StatusBar = env->addStaticText (L"", rectStatusBar, true, false);
	
	MyEventReceiver receiver(context);
	device->setEventReceiver(&receiver);
	
	while(device->run() && driver)
	{
		if (device->isWindowActive())
		{
			driver->beginScene(true, true, SColor(0,200,200,200));
	
			env->drawAll();
		
			driver->endScene();
		}
	}

	device->drop();

	return 0;
}
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Post Reply