View Single Post
Old 05 July 2021, 15:57   #1
Warty
Registered User
 
Join Date: Aug 2018
Location: Minneapolis, USA
Posts: 301
Converting to Reaction: Shared UserPort?

I have an app designed without Reaction, and now that 3.2 is available, I'm trying to convert it to work with Reaction. One of the things that is different is event handling. I may describe this wrong, but this is how I think the differences come out:
  • Pre-reaction: we use messages. Do GetMsg, do stuff, do ReplyMsg
  • In Reaction, we don't use messages. You do GetAttr for the window to get its signal, wait on the signal (same as pre-reaction), then loop through RA_HandleInput() until it is out of messages (ok, IT uses messages?) - WMHI_LASTMSG

My app uses windows like this:
- a backdrop window, opened on launch
- user opens 1 to n additional windows as they want to. Its basically a file manager, so if you double click on a file icon for a folder, another window opens showing contents of that folder.
- you can do an About menu item and an About Window opens.
- other window types to come (config, etc.)

I added the About Window after reaction came out, so it has been my testbed. There will only ever be 1 about window open, so it's pretty straight forward.

But the main window type, there could be any number of them. I am using a shared userPort for all of them.

When a signal comes in:
- is it for the about window? let it process it. STOP
- is it for the app reply port? let the app handle that. STOP
- is it for the shared user port?
- Get the message
- Get the IDCMPWindow property from the message
- iterate through the list of open windows to find a match (I have a parent class for windows that wraps the Intuition struct Window).
- Let that window class handle the message and reply.


Is it possible to use a shared signal with Reaction windows? What's the best design for a case like this?

- Do GetAttr for each window as it is made, and store that in the parent window class. add all those signals together in the signal mask, then iterate through to find out which one it was?
- something else entirely?

Current event handler:
Code:
// wait for events for the currently active window.
// having it centralized makes it possible to have user close first window gracefully
// requires that WBSurfaces keep track of which one is active, which isn't hard.
void WaitForEvents(void)
{
	WindowRequiredAction	action_needed = action_none;
	struct					IntuiMessage* the_message;
	struct					Window* window_with_message;
	ULONG					window_event_signal = 1L << global_app->shared_user_port_->mp_SigBit;
	ULONG					launched_app_signal = 1L << global_app->launched_app_reply_port_->mp_SigBit;
	ULONG					our_idcmp_signals = window_event_signal | launched_app_signal;
	ULONG					about_window_signal;
	ULONG					signals_we_want;
	ULONG					signals_received;

	// LOGIC:
	//   we will listen at 2 ports:
	//   - one for window events. this is the user user port that we set for all WB2KSurfaces
	//   - one that we set up to be a port where apps we launch can reply back to when they are quit
	//   we combine all signals (2 in this case), then use Wait() instead of WaitPort().
	//   we also need to listen on a per-window basis for Reaction signals, as reaction does not seem to work with shared ports
	//     at current time (6/30/2021), only About window uses reaction, so we can check for that window specifically
	//     need a more dynamic solution when we move the main window type to reaction (iterating through all app's surfaces is probably slow)

	
	while (action_needed != action_quit_app)
	{
		signals_we_want = our_idcmp_signals;
		
		if (global_app->about_window_ != NULL)
		{
			GetAttr(WINDOW_SigMask, global_app->about_window_->objects_[ABOUT_OID_MAIN], &about_window_signal);
			signals_we_want |= about_window_signal;
 		}

		signals_received = Wait(signals_we_want);

		if (signals_received & about_window_signal)
		{
			//DEBUG_OUT(("WaitForEvents %d: about win reaction signal detected!", __LINE__));

			action_needed = AboutWindow_HandleEvents(global_app->about_window_);

			if (action_needed == action_close_window)
			{
				App_CloseAboutWindow(global_app);
			}
		}
		else if (signals_received & launched_app_signal)
		{
			//DEBUG_OUT(("WaitForEvents %d: launched_app_signal received", __LINE__));
			App_HandleLaunchedAppSignal();			
		}
		else if (signals_received & window_event_signal)
		{
			//DEBUG_OUT(("WaitForEvents %d: window_event_signal received", __LINE__));

			while ((the_message = (struct IntuiMessage*)GetMsg(global_app->shared_user_port_)) != NULL)
			{
				// determine which window this event was directed at
				// acquire the message, because it has a pointer to the window struct
				//the_message = (struct IntuiMessage*)GetMsg(global_app->shared_user_port_);
				window_with_message = the_message->IDCMPWindow;

				//DEBUG_OUT(("WaitForEvents %d: window_with_message=%p", __LINE__, window_with_message));

				WB2KList*	the_item = *(global_app->list_surfaces_);
				
				if ( the_item == NULL )
				{
					LOG_WARN(("WaitForEvents %d: no windows available??", __LINE__));
				}
				else
				{
					boolean signal_not_matched = true;

					while (the_item != NULL)
					{
						WB2KWindow* this_surface = (WB2KWindow*)(the_item->payload_);

						//DEBUG_OUT(("WaitForEvents %d: window_with_message=%p; this_surface=%p", __LINE__, window_with_message, this_surface->window_));

						// is this the item we are looking for?
						if (this_surface->window_ == window_with_message)
						{
							//printf("WaitForEvents: event detected for surface %p, window %p \n", this_surface, this_surface->window_);
							signal_not_matched = false;
							this_surface->intuimsg_ = the_message;
							action_needed = Window_HandleEvents(this_surface);

							if (action_needed == action_close_window)
							{
								App_CloseOneWindow(global_app, the_item);
							}

							break;
						}						

						the_item = the_item->next_item_;
					}

					if (signal_not_matched)
					{
						LOG_ERR(("WaitForEvents %d: a message couldn't be matched to a window", __LINE__));
						App_Destroy(); // crash early, crash often
					}
				}
			}
		}
	}
}
Warty is offline  
 
Page generated in 0.04498 seconds with 11 queries