Focus issues on scripted panels containing custom QWidgets

Focus issues on scripted panels containing custom QWidgets

Anonymous
Not applicable
1,446 Views
7 Replies
Message 1 of 8

Focus issues on scripted panels containing custom QWidgets

Anonymous
Not applicable

We're experiencing some focus issues that happen to slow down our artists tremendously "when it happens".

 

Let's describe the setup:

- we have a scripted panel in one of the view panes

- it contains a form layout, which in turn hosts our custom QWidget (a text editor with its own clipboard)

 

Say the user selects a mesh in a viewport and presses CTRL+C on accident.  He then continues to move the mouse over our panel and presses CTRL.  The panel immediately gets a thin border painted around - which should indicate the panel has focus.  If he then presses CTRL+V, the mesh gets copied into the scene.

As the border around the scripted panel indicates focus, we'd expect it to use the internal text-clipboard and insert text.

 

I've done further investigations, installing event filters on all parents of our QWidget up to and including the scriptedPanels parent layout.  NONE of them receives FocusInEvents when pressing CTRL.  Also checking via QWidget::hasFocus() yields "false".  This explains why the copying happens.

 

The only events the widgets receive are "enter/leave" and "paint" events (ok, also tooltip events ...).

 

Can anybody tell how I can get ahold of that "soft focus" of Maya, to set the "hard focus" to my editor?

0 Likes
Accepted solutions (1)
1,447 Views
7 Replies
Replies (7)
Message 2 of 8

cheng_xi_li
Autodesk Support
Autodesk Support

Hi sh,

 

I've discussed this with our engineer, we are not very clear at your problem. We made an assumption that your widget is trying to get the focus while mouse entered and CTRL is pressed, is that correct? To help us understand your problem better, can your provide a video to show us your issue? Moreover, if you can provide a sample code to reproduce the issue for us, it would be better for us to understand your issue.

 

Yours,

Li

0 Likes
Message 3 of 8

Anonymous
Not applicable

Hi Cheng,

 

your assumption is wrong, the widget does not try anything.  A Video is a good idea, but I doubt my artists will have the time to create one.  So for now I'll try to use words to make the actual issue more clear.

 

Maya draws a thin light border around the pane, that is supposed to be "in focus" at every moment.  By pressing CTRL, SHIFT, or ALT, the user switches this "soft focus" to the pane, where the mouse pointer is currently hovering over.  You can try this out very easily: simply start up Maya, select a 4-pane-setup, then move the mouse over the view panes and press CTRL.  Every time the mouse cursor is over another pane, the "soft focus"-border switches over to the other pane.

 

Technically spoken, this is no real input focus.  If the pane containing my editor widget has "soft focus", the 

editorWidget->hasFocus()

does not necessarily return "true".

 

The problem is, that the artist perceives the thin light border around the pane as it having full input focus.  Now if the artist presses CTRL+V when our editor has soft focus, he expects the last copied text to be inserted in our editor.  But actually the last sceneClipBoard gets inserted into the scene, because the thin border is no real input focus indicator and the current application focus is somewhere in the scene, still.

 

My question is: "how do I get to know, that my scriptedPanel (containing the editor) has just received the soft focus?"

 

0 Likes
Message 4 of 8

cheng_xi_li
Autodesk Support
Autodesk Support
After talking with our engineer,  it seems that there’s no way to be notified when a panel is soft focused. Because it is implemented in Maya internally. To solve the issue, user has to process the keyboard/mouse event by themselves.
 
Here is a sample to show user how to set the soft focus on a panel by move the cursor on the panel and press ctrl key
 
 
from PySide.QtGui import *
from PySide.QtCore import *
 
class QtKeyPressListener(QObject):
    def __init__(self):
        QObject.__init__(self)
 
    def eventFilter(self, obj, event):
        if event.type() == QEvent.KeyPress:
            if event.modifiers() == Qt.ControlModifier:
                cpName = cmds.getPanel(atPosition=[QCursor.pos().x(), QCursor.pos().y()])
                if cpName != None:
                    cmds.setFocus(cpName)
                    print cpName                      
                     
        return QObject.eventFilter(self, obj, event)
           
keyLinstener = QtKeyPressListener()
qApp.installEventFilter(keyLinstener)
 
 
Please try it and let me know if you can run it on your machine, please take care of the tab and indent, to remove the filter, please run:
qApp.removeEventFilter(keyLinstener)
0 Likes
Message 5 of 8

Anonymous
Not applicable

Dear Cheng,

 

well, then it looks as if there is no real solution.  I would never install an event listener on the application object and leave it running all the time, that's just too much of a hack ...

 

I think the better way would be to selectively install the event filter after receiving QEnterEvent, if my Widget is not in focus.  Then monitor keystrokes of the modifier keys.  If any modifier key gets pressed before the EndListeningCondition is met, "hard focus" gets set to my widget.

 

EndListeningConditions ... we better define as many as could be identified, because such an event listener can produce severe side effects destroying artist workflow.

- QLeaveEvent

- mouse button press

- keyboard-modifier-press

- application deactivated

- window deactivated

 

I think, I'll give it a shot.

0 Likes
Message 6 of 8

Anonymous
Not applicable
Oh, what I just saw when reading your code: you should never call the inherited eventFilter! EventFilter is supposed to be declared/inherited if you need it, and it should return a bool indicating if further processing of the event is forbidden.
0 Likes
Message 7 of 8

Anonymous
Not applicable
Accepted solution

Looks as if indeed this is a solution:

  • I already had MyEditor::event() implemented, so I added the following to trigger and untrigger the event filtering:

 

bool MyEditor::event (	QEvent *event	)
{
	[...]
	if(event->type() == QEvent::Enter)
	{
		if ( !( (focusedChild != NULL) || eventFilterActive ) )
		{
			eventFilterActive = true;
			QApplication::instance()->installEventFilter(this);
		}
	}
	if(eventFilterActive)
	{
		switch(event->type())
		{
		case QEvent::Leave:
		case QEvent::ApplicationDeactivate:
		case QEvent::WindowDeactivate:
		case QEvent::MouseButtonPress:
			QApplication::instance()->removeEventFilter(this);
			eventFilterActive = false;
			break;
		}
	}
	return retval;
}
  • as there are very few child-child-widgets of my editor that may receive focus, I had to watch those grandchildren to have a simple method of determining current editor focus state.  So they get the eventFilter installed, too.
  • now the eventFilter itself:
bool MyEditor::eventFilter(QObject *object, QEvent *event)
{
	if (	( object == rightEditor )		||
			( object == leftEditor )	||
			( object == findCombo )			||
			( object == replaceCombo )		)
	{
		switch ( event->type() )
		{
		case QEvent::FocusIn:	focusedChild = qobject_cast<QWidget*>(object);
								if(eventFilterActive)
								{
									QApplication::instance()->removeEventFilter(this);
									eventFilterActive = false;
								}
								break;
		case QEvent::FocusOut:	focusedChild = NULL;
								break;
		}
	}
	else
	{
		if ( event->type() == QEvent::KeyPress )
		{
			QKeyEvent * ke = dynamic_cast<QKeyEvent*>(event);
			if(ke)
			{
				switch(ke->key())
				{
				case Qt::Key_Shift:
				case Qt::Key_Control:
				case Qt::Key_Meta:
				case Qt::Key_Alt:
				case Qt::Key_AltGr:
				case Qt::Key_Menu:
					QWidget *ca(childAt(QWidget::mapFromGlobal(QCursor::pos())));
					if(ca) ca->setFocus();
					QApplication::instance()->removeEventFilter(this);
					eventFilterActive = false;
					break;
				}
			}
		}
	}
	return false;
}

 

0 Likes
Message 8 of 8

Anonymous
Not applicable

P.S.: somebody may want to make the tab-width of code-blocks 4 characters in this forum...

0 Likes