예제 #1
0
//-----------------------------------------------------------------------------
// Purpose: Called whenever a panel is constructed
//-----------------------------------------------------------------------------
void CVGui::PanelCreated(VPanel *panel)
{
	UtlHandle_t h = m_HandleTable.AddHandle();
	m_HandleTable.SetHandle( h, panel );

#if DUMP_PANEL_LIST
	int nCount = m_HandleTable.GetHandleCount();
	int nActualCount = 0;
	for ( int i = 0; i < nCount; ++i )
	{
		UtlHandle_t h = m_HandleTable.GetHandleFromIndex( i );
		if ( m_HandleTable.IsHandleValid( h ) )
		{
			++nActualCount;
		}
	}

	if ( nActualCount >= WARN_PANEL_NUMBER )
	{
		FILE *file1 = fopen("panellist.txt", "w");
		if (file1 != NULL)
		{
			fprintf(file1, "Too many panels...listing them all.\n");
			int panelIndex;
			for (panelIndex = 0; panelIndex < nCount; ++panelIndex)
			{
				UtlHandle_t h = m_HandleTable.GetHandleFromIndex( i );
				VPanel *pPanel = m_HandleTable.GetHandle( h );
				IClientPanel *ipanel = ( pPanel ) ? pPanel->Client() : NULL;
				if ( ipanel )
					fprintf(file1, "panel %d: name: %s   classname: %s\n", panelIndex, ipanel->GetName(), ipanel->GetClassName());
				else
					fprintf(file1, "panel %d: can't get ipanel\n", panelIndex);
			}

			fclose(file1);
		}
	}

	Assert( nActualCount < WARN_PANEL_NUMBER );
#endif // DUMP_PANEL_LIST

	((VPanel *)panel)->SetHPanel( h );

	g_pSurface->AddPanel((VPANEL)panel);
}
예제 #2
0
//-----------------------------------------------------------------------------
// Purpose: message pump
//			loops through and sends all active messages
//			note that more messages may be posted during the process
//-----------------------------------------------------------------------------
bool CVGui::DispatchMessages()
{
	int time = g_pSystem->GetTimeMillis();

	m_InDispatcher = true;
	bool doneWork = (m_MessageQueue.Count() > 12);

	bool bUsingDelayedQueue = (m_DelayedMessageQueue.Count() > 0);

	// Need two passes because we send the mouse move message after all
	// other messages are done, but the mouse move message may itself generate
	// some more messages
	int nPassCount = 0;
	while ( nPassCount < 2 )
	{
		while (m_MessageQueue.Count() > 0 || (m_SecondaryQueue.Count() > 0) || bUsingDelayedQueue)
		{
			// get the first message
			MessageItem_t *messageItem = NULL;
			int messageIndex = 0;

			// use the secondary queue until it empties. empty it after each message in the
			// primary queue. this makes primary messages completely resolve 
			bool bUsingSecondaryQueue = (m_SecondaryQueue.Count() > 0);
			if (bUsingSecondaryQueue)
			{
				doneWork = true;
				messageIndex = m_SecondaryQueue.Head();
				messageItem = &m_SecondaryQueue[messageIndex];
			}
			else if (bUsingDelayedQueue)
			{
				if (m_DelayedMessageQueue.Count() >0)
				{
					messageItem = (MessageItem_t*)&m_DelayedMessageQueue.ElementAtHead();
				}
				if (!messageItem || messageItem->_arrivalTime > time)
				{
					// no more items in the delayed message queue, move to the system queue
					bUsingDelayedQueue = false;
					continue;
				}
			}
			else
			{
				messageIndex = m_MessageQueue.Head();
				messageItem = &m_MessageQueue[messageIndex];
			}

			// message debug code 

			if ( m_bDebugMessages )
			{
				char *qname = bUsingSecondaryQueue ? "Secondary" : "Primary";

				if (strcmp(messageItem->_params->GetName(), "Tick")
					&& strcmp(messageItem->_params->GetName(), "MouseFocusTicked") 
					&& strcmp(messageItem->_params->GetName(), "KeyFocusTicked")
					&& strcmp(messageItem->_params->GetName(), "CursorMoved"))
				{
					if (!stricmp(messageItem->_params->GetName(), "command"))
					{
						g_pIVgui->DPrintf2( "%s Queue dispatching command( %s, %s -- %i )\n", qname, messageItem->_params->GetName(), messageItem->_params->GetString("command"), messageItem->_messageID );
					}
					else
					{
						g_pIVgui->DPrintf2( "%s Queue dispatching( %s -- %i )\n", qname ,messageItem->_params->GetName(), messageItem->_messageID );
					}
				}
			}

			// send it
			KeyValues *params = messageItem->_params;

			// Deal with special internal cursor movement messages
			if ( messageItem->_messageTo == 0xFFFFFFFF )
			{
				if ( !Q_stricmp( params->GetName(), "SetCursorPosInternal" ) )
				{
					int nXPos = params->GetInt( "xpos", 0 );
					int nYPos = params->GetInt( "ypos", 0 );
					g_pInput->UpdateCursorPosInternal( nXPos, nYPos );
				}
			}
			else
			{
				VPanel *vto = (VPanel *)g_pIVgui->HandleToPanel(messageItem->_messageTo);
				if (vto)
				{
					//			Msg("Sending message: %s to %s\n", params ? params->GetName() : "\"\"", vto->GetName() ? vto->GetName() : "\"\"");
					vto->SendMessage(params, g_pIVgui->HandleToPanel(messageItem->_from));
				}
			}

			// free the keyvalues memory
			// we can't reference the messageItem pointer anymore since the queue might have moved in memory
			if (params)
			{
				params->deleteThis();
			}

			// remove it from the queue
			if (bUsingSecondaryQueue)
			{
				m_SecondaryQueue.Remove(messageIndex);
			}
			else if (bUsingDelayedQueue)
			{
				m_DelayedMessageQueue.RemoveAtHead();
			}
			else
			{
				m_MessageQueue.Remove(messageIndex);
			}
		}

		++nPassCount;
		if ( nPassCount == 1 )
		{
			// Specifically post the current mouse position as a message
			g_pInput->PostCursorMessage();
		}
	}

	// Make sure the windows cursor is in the right place after processing input 
	// Needs to be done here because a message provoked by the cursor moved
	// message may move the cursor also
	g_pInput->HandleExplicitSetCursor( );

	m_InDispatcher = false;
	return doneWork;
}
예제 #3
0
//-----------------------------------------------------------------------------
// Purpose: Calculates which panel the cursor is currently over and sets it up
//			as the current mouse focus.
//-----------------------------------------------------------------------------
void CInputWin32::UpdateMouseFocus(int x, int y)
{
	// find the panel that has the focus
	VPanel *focus = NULL; 

	InputContext_t *pContext = GetInputContext( m_hContext );

	if (!pContext->_rootPanel)
	{
		if (surface()->IsCursorVisible() && surface()->IsWithin(x, y))
		{
			// faster version of code below
			// checks through each popup in order, top to bottom windows
			for (int i = surface()->GetPopupCount() - 1; i >= 0; i--)
			{
				VPanel *popup = (VPanel *)surface()->GetPopup(i);
				VPanel *panel = popup;
				bool wantsMouse = panel->IsMouseInputEnabled();
				bool isVisible;

				do 
				{
					isVisible = panel->IsVisible();
					panel = panel->GetParent();
				}
				while ( isVisible && panel && panel->GetParent() ); // only consider panels that want mouse input

				if ( wantsMouse && isVisible ) 
				{
					focus = (VPanel *)popup->Client()->IsWithinTraverse(x, y, false);
					if (focus)
						break;
				}
			}
			if (!focus)
			{
				focus = (VPanel *)((VPanel *)surface()->GetEmbeddedPanel())->Client()->IsWithinTraverse(x, y, false);
			}
		}
	}
	else
	{
		focus = (VPanel *)((VPanel *)(pContext->_rootPanel))->Client()->IsWithinTraverse(x, y, false);
	}

	// mouse focus debugging code
	/*
	static VPanel *oldFocus = (VPanel *)0x0001;
	if (oldFocus != focus)
	{
		oldFocus = focus;
		if (focus)
		{
			ivgui()->DPrintf2("mouse over: (%s, %s)\n", focus->GetName(), focus->GetClassName());
		}
		else
		{
			ivgui()->DPrintf2("mouse over: (NULL)\n");
		}
	}
	*/

	// check if we are in modal state, 
	// and if we are make sure this panel is a child of us.
	if (!IsChildOfModalPanel((VPANEL)focus))
	{	
		// should this be _appModalPanel?
		focus = NULL;
	}

	SetMouseFocus((VPANEL)focus);
}
예제 #4
0
//-----------------------------------------------------------------------------
// Purpose: Sets the new mouse focus
//			won't override _mouseCapture settings
// Input  : newMouseFocus - 
//-----------------------------------------------------------------------------
void CInputWin32::SetMouseFocus(VPANEL newMouseFocus)
{
	// check if we are in modal state, 
	// and if we are make sure this panel is a child of us.
	if (!IsChildOfModalPanel(newMouseFocus))
	{	
		return;	
	}

	bool wantsMouse, isPopup; // =  popup->GetMouseInput();
	VPanel *panel = (VPanel *)newMouseFocus;

	InputContext_t *pContext = GetInputContext( m_hContext );

	
	if ( newMouseFocus )
	{
		do 
		{
			wantsMouse = panel->IsMouseInputEnabled();
			isPopup = panel->IsPopup();
			panel = panel->GetParent();
		}
		while ( wantsMouse && !isPopup && panel && panel->GetParent() ); // only consider panels that want mouse input
	}

	// if this panel doesn't want mouse input don't let it get focus
	if (newMouseFocus && !wantsMouse) 
	{
		return;
	}

	if ((VPANEL)pContext->_mouseOver != newMouseFocus || (!pContext->_mouseCapture && (VPANEL)pContext->_mouseFocus != newMouseFocus) )
	{
		pContext->_oldMouseFocus = pContext->_mouseOver;
		pContext->_mouseOver = (VPanel *)newMouseFocus;

		//tell the old panel with the mouseFocus that the cursor exited
		if (pContext->_oldMouseFocus != NULL)
		{
			// only notify of entry if the mouse is not captured or we're a child of the captured panel
			if ( !pContext->_mouseCapture || pContext->_oldMouseFocus->HasParent(pContext->_mouseCapture) )
			{
				ivgui()->PostMessage((VPANEL)pContext->_oldMouseFocus, new KeyValues("CursorExited"), NULL);
			}
		}

		//tell the new panel with the mouseFocus that the cursor entered
		if (pContext->_mouseOver != NULL)
		{
			// only notify of entry if the mouse is not captured or we're a child of the captured panel
			if ( !pContext->_mouseCapture || pContext->_mouseOver->HasParent(pContext->_mouseCapture) )
			{
				ivgui()->PostMessage((VPANEL)pContext->_mouseOver, new KeyValues("CursorEntered"), NULL);
			}
		}

		// set where the mouse is currently over
		// mouse capture overrides destination
		if ( pContext->_mouseCapture )
		{
			pContext->_mouseFocus = pContext->_mouseCapture;
		}
		else
		{
			pContext->_mouseFocus = pContext->_mouseOver;
		}
	}
}
예제 #5
0
//-----------------------------------------------------------------------------
// Purpose: Calculate the new key focus
//-----------------------------------------------------------------------------
VPanel *CInputWin32::CalculateNewKeyFocus()
{
	InputContext_t *pContext = GetInputContext(m_hContext);

	// get the top-order panel
	VPanel *top = NULL;
	VPanel *wantedKeyFocus = NULL;

	if (!pContext->_rootPanel)
	{
		if (surface()->GetPopupCount() > 0)
		{
			// find the highest-level window that is both visible and a popup
			int index = surface()->GetPopupCount();
			
			while (index)
			{
				
				top = (VPanel *)surface()->GetPopup(--index);

				// traverse the heirachy and check if the popup really is visible
				if (top->IsPopup() && top->IsVisible() && top->IsKeyBoardInputEnabled() && !surface()->IsMinimized((VPANEL)top))
				{
					bool IsVisible = top->IsVisible();
					VPanel *p = top->GetParent();
					// drill down the heirachy checking that everything is visible
					while(p && IsVisible)
					{
						if( p->IsVisible()==false)
						{
							IsVisible=false;
							break;
						}
						p=p->GetParent();
					}

					if (IsVisible && !surface()->IsMinimized((VPANEL)top) )
					{
						break;
					}
				}
				
				top = NULL;
			} 
		}
	}
	else
	{
		top = (VPanel *)pContext->_rootPanel;
	}

	if (top)
	{
		// ask the top-level panel for what it considers to be the current focus
		wantedKeyFocus = (VPanel *)top->Client()->GetCurrentKeyFocus();
		if (!wantedKeyFocus)
		{
			wantedKeyFocus = top;

		}
	}

	// check to see if any of this surfaces panels have the focus
	if (!surface()->HasFocus())
	{
		wantedKeyFocus=NULL;
	}

	// check if we are in modal state, 
	// and if we are make sure this panel is a child of us.
	if (!IsChildOfModalPanel((VPANEL)wantedKeyFocus))
	{	
		wantedKeyFocus=NULL;
	}

	return wantedKeyFocus;
}
예제 #6
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CInputWin32::RunFrame()
{
	InputContext_t *pContext = GetInputContext(m_hContext);

	if (m_hContext == DEFAULT_INPUT_CONTEXT)
	{
		_updateToggleButtonState = true;

	/*	FIXME: add the set cursor call?
		// make sure the cursor looks like it is supposed to
		if (pContext->_mouseFocus)
		{
			pContext->_mouseFocus->Client()->InternalSetCursor();
		}*/
	}


	// tick whoever has the focus
	if (pContext->_keyFocus)
	{
		// when modal dialogs are up messages only get sent to the dialogs children.
		if (IsChildOfModalPanel((VPANEL)pContext->_keyFocus))
		{	
			ivgui()->PostMessage((VPANEL)pContext->_keyFocus, new KeyValues("KeyFocusTicked"), NULL);
		}
	}

	// tick whoever has the focus
	if (pContext->_mouseFocus)
	{
		// when modal dialogs are up messages only get sent to the dialogs children.
		if (IsChildOfModalPanel((VPANEL)pContext->_mouseFocus))
		{	
			ivgui()->PostMessage((VPANEL)pContext->_mouseFocus, new KeyValues("MouseFocusTicked"), NULL);
		}
	}

	//clear mouse and key states
	for (int i = 0; i < MOUSE_LAST; i++)
	{
		pContext->_mousePressed[i] = 0;
		pContext->_mouseDoublePressed[i] = 0;
		pContext->_mouseReleased[i] = 0;
	}
	for (i = 0; i < KEY_LAST; i++)
	{
		pContext->_keyPressed[i] = 0;
		pContext->_keyTyped[i] = 0;
		pContext->_keyReleased[i] = 0;
	}

	VPanel *wantedKeyFocus = CalculateNewKeyFocus();

	// make sure old and new focus get painted
	if (pContext->_keyFocus != wantedKeyFocus)
	{
		if (pContext->_keyFocus != NULL)
		{
			pContext->_keyFocus->Client()->InternalFocusChanged(true);

			// send a message to the window saying that it's losing focus
			ivgui()->PostMessage((VPANEL)pContext->_keyFocus, new KeyValues("KillFocus"), NULL);

			pContext->_keyFocus->Client()->Repaint();

			// repaint the nearest popup as well, since it will need to redraw after losing focus
			VPanel *dlg = pContext->_keyFocus;
			while (dlg && !dlg->IsPopup())
			{
				dlg = dlg->GetParent();
			}
			if (dlg)
			{
				dlg->Client()->Repaint();
			}
		}
		if (wantedKeyFocus != NULL)
		{
			wantedKeyFocus->Client()->InternalFocusChanged(false);

			// send a message to the window saying that it's gaining focus
			ivgui()->PostMessage((VPANEL)wantedKeyFocus, new KeyValues("SetFocus"), NULL);
			wantedKeyFocus->Client()->Repaint();

			// repaint the nearest popup as well, since it will need to redraw after gaining focus
			VPanel *dlg = wantedKeyFocus;
			while (dlg && !dlg->IsPopup())
			{
				dlg = dlg->GetParent();
			}
			if (dlg)
			{
				dlg->Client()->Repaint();
			}
		}

		// accept the focus request
		pContext->_keyFocus = wantedKeyFocus;
		if (pContext->_keyFocus)
		{
			pContext->_keyFocus->MoveToFront();
		}
	}
}