Troubles in Commodity-land

A forum for general AmigaOS 4.x support questions that are not platform-specific
User avatar
broadblues
AmigaOS Core Developer
AmigaOS Core Developer
Posts: 600
Joined: Sat Jun 18, 2011 2:40 am
Location: Portsmouth, UK
Contact:

Re: Troubles in Commodity-land

Post by broadblues »

The proliferation of global hotkeys can make it difficult for a programmer or user to find an unused global hotkey combination that's not already in use.
There are 26 letter keys and 5 qualifiers (6 / 7 if you separate right and left alt and shift)

That makes 26 * 5! or 3120 combinations, admitedly a few those require you to use your toes as well as both hands but still using any two qualifirs from 5 gives 26 * 5 * 4 = 520 options. More if you add number and punctuation keys.

The possibilty of clash is why you should use the CX_POPKEY tooltype for customisation. (or similar) Few people run more than 5 or size commodities.

Lack of 'hotkey space' simply isn't an issue.
User avatar
broadblues
AmigaOS Core Developer
AmigaOS Core Developer
Posts: 600
Joined: Sat Jun 18, 2011 2:40 am
Location: Portsmouth, UK
Contact:

Re: Troubles in Commodity-land

Post by broadblues »

xenic wrote: Personally, I'd rather see it implemented in Intuition and available in traditional widows (for older ported programs) and window class with the simple addition of a Tag item or arg. However, any improvement would be appreciated.
Not really suitable, it's not related to windows rather application level.

I would argue that a app should not have a popkey unless it has a 'hidden' feature, ie it's a commodity with a hideable GUI, as opposed to an iconifyable one. Workbench has a keyboard mechaism for selecting an acivating icons already.
User avatar
trixie
Posts: 409
Joined: Thu Jun 30, 2011 2:54 pm
Location: Czech Republic

Re: Troubles in Commodity-land

Post by trixie »

@broadblues

Good points.
The Rear Window blog

AmigaOne X5000 @ 2GHz / 4GB RAM / Radeon RX 560 / ESI Juli@ / AmigaOS 4.1 Final Edition
SAM440ep-flex @ 667MHz / 1GB RAM / Radeon 9250 / AmigaOS 4.1 Final Edition
xenic
Posts: 1185
Joined: Sun Jun 19, 2011 12:06 am

Re: Troubles in Commodity-land

Post by xenic »

broadblues wrote: Not really suitable, it's not related to windows rather application level.

I would argue that a app should not have a popkey unless it has a 'hidden' feature, ie it's a commodity with a hideable GUI, as opposed to an iconifyable one. Workbench has a keyboard mechaism for selecting an acivating icons already.
I use a lot of seperate screens and after I've iconified a program from a seperate screen to reduce screen crowding, I find it convenient to be able to reopen the iconified program with a hotkey rather than switching to the Workbench screen, clicking the icon and then returning to the screen I'm working on.

On the other hand, I can see how Commodities hotkey use can be abusive. I still use Turbotext which allows unlimited global hotkeys to be defined. I recently discovered why some hotkeys are unavailabe for "REAL" commodity use. Turbotext defines 5 global hotkeys in the default preferences. Ugh, bad idea; I need to get rid of those.


™
AmigaOne X1000 with 2GB memory - OS4.1 FE
xenic
Posts: 1185
Joined: Sun Jun 19, 2011 12:06 am

Re: Troubles in Commodity-land

Post by xenic »

I've converted the PopShell.c example to OS4 and removed all Commodity related amigalib function calls. I'm not sure I should try to replace the Input Event amigalib functions or if it's practical. I'm posting the converted code here to see if anyone finds any errors or helpful changes. I tried to stick with the original structure of the example, so the changes make the lines longer than I would normally like. Here's my OS4 version of the PopShell.c example:
:

Code: Select all

/* PopShell.c - Simple hot key commodity example for OS4.
   Compile commands: gcc PopShell.c -o popshell -lamiga -Wall

   To run the compiled program - Open 2 shell windows. Execute
   PopShell in the first shell window with a line like:
     PopShell HOTKEY "ctrl alt f"
   Activate the second shell window and enter the keyboard shortcut.
   A new shell window should open on the Workbench screen.
*/

#include <libraries/commodities.h>

#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/commodities.h>
#include <clib/alib_protos.h>
#include <stdio.h>
#include <signal.h>

static CONST_STRPTR version USED = "$VER: PopShell 1.0 (04.11.2015)";
static CONST_STRPTR stackcookie USED = "$STACK: 32768";

#define EVT_HOTKEY 1L
struct Library *CxBase = NULL;
struct CommoditiesIFace *ICommodities = NULL;

struct MsgPort *broker_mp = NULL;
CxObj *broker, *filter, *sender, *translate;

struct NewBroker newbroker =
{
	NB_VERSION,
	"Amiga PopShell",       /* string to identify this broker */
	"A Simple PopShell",
	"A simple PopShell commodity",
	NBU_UNIQUE | NBU_NOTIFY,      /* Don't want any new commodities starting with this name. */
	0, 0, 0, 0                    /* If someone tries it, let me know */
};

STRPTR newshell = "\rllehswen";  /* "newshell" spelled backwards */
struct InputEvent *ie = NULL;
ULONG cxsigflag;

#define TEMPLATE "HOTKEY/K,CX_PRIORITY/N"
enum
{
	ARG_HOTKEY, ARG_PRIORITY, ARG_MAX
};

void ProcessMsg(void);

int main(int argc, char **argv)
{
	STRPTR hotkey = NULL;
	CxMsg *msg = NULL;
	struct RDArgs *argsdata = NULL;
	int32 rargs[ARG_MAX] = {0};
	BYTE priority = 0;

	signal(SIGINT, SIG_IGN);

	if ((CxBase = IExec->OpenLibrary("commodities.library", 37L)))
	{
		if ((ICommodities = (struct CommoditiesIFace *)IExec->GetInterface(CxBase,"main",1,NULL)))
		{
			if ((argsdata = IDOS->ReadArgs(TEMPLATE, rargs, NULL)))
			{
				if (rargs[ARG_PRIORITY])
					priority = (BYTE)*(uint32 *)rargs[ARG_PRIORITY];
				if ((broker_mp = IExec->AllocSysObject(ASOT_PORT, NULL)))
				{
					newbroker.nb_Port = broker_mp;
					cxsigflag = 1L << broker_mp->mp_SigBit;
					newbroker.nb_Pri = priority;
					hotkey = (STRPTR)rargs[ARG_HOTKEY];

					if ((broker = ICommodities->CxBroker(&newbroker, NULL)))
					{
						/* CxFilter(), CxSender() & CxTranslate() are      */
						/* macros defined in libraries/commodities.h.     */
						/* CxFilter() creates a filter CxObject.                  */
						/* CxSender() creates a sender CxObject.          */
						/* CxTranslate() creates a translation CxObject. */
						if ((filter = CxFilter(hotkey)))
						{
							/* Add a filter CxObject to another's personal list. */
							ICommodities->AttachCxObj(broker, filter);

							/* Add a sender CxObject to the filter CxObject. */
							ICommodities->AttachCxObj(filter,CxSender(broker_mp, EVT_HOTKEY));

							/* Add a translation CxObject to the filter CxObject */
							ICommodities->AttachCxObj(filter,CxTranslate(NULL));

							if (!(ICommodities->CxObjError(filter)))
							{
								/* InvertString() is an amiga.lib function that creates a linked */
								/* list of input events which would translate into the string    */
								/* passed to it.  Note that it puts the input events in the      */
								/* opposite order in which the corresponding letters appear in   */
								/* the string.  A translate CxObject expects them backwards.     */
								if ((ie = InvertString(newshell, NULL)))
								{
									ICommodities->ActivateCxObj(broker, 1L);
									ProcessMsg();
									/* we have to release the memory allocated by InvertString. */
									FreeIEvents(ie);
								}
							}
						}
						/* DeleteCxObjAll() is a commodities.library function that */
						/* deletes the CxObject pointed to in its argument and     */
						/* deletes all of the CxObjects attached to it.            */
						ICommodities->DeleteCxObjAll(broker);

						/* Empty the port of all CxMsgs */
						while((msg = (CxMsg *)IExec->GetMsg(broker_mp)))
							IExec->ReplyMsg((struct Message *)msg);
					}
					IExec->FreeSysObject(ASOT_PORT, broker_mp);
				}
				IDOS->FreeArgs(argsdata); /* cleans up after ReadArgs() */
			}
			IExec->DropInterface((struct Interface *)ICommodities);
		}
		IExec->CloseLibrary(CxBase);
	}
	return RETURN_OK;
}

void ProcessMsg(void)
{
	extern struct MsgPort *broker_mp;
	extern CxObj *broker;
	extern ULONG cxsigflag;
	CxMsg *msg = NULL;
	ULONG sigrcvd, msgid, msgtype;
	LONG returnvalue = 1L;

	while (returnvalue)
	{
		sigrcvd = IExec->Wait(SIGBREAKF_CTRL_C | cxsigflag);

		while((msg = (CxMsg *)IExec->GetMsg(broker_mp)))
		{
			msgid = ICommodities->CxMsgID(msg);
			msgtype = ICommodities->CxMsgType(msg);
			IExec->ReplyMsg((struct Message *)msg);

			switch(msgtype)
			{
				case CXM_IEVENT:
					printf("A CXM_EVENT, ");
					switch(msgid)
					{
						case EVT_HOTKEY:
							/* We got the message from the sender CxObject  */
							printf("You hit the HotKey.\n");
							/* Add the string "newshell" to input * stream. */
							/*  If a shell gets it, it'll open a new shell. */
							ICommodities->AddIEvents(ie);
							break;
						default:
							printf("unknown.\n");
							break;
					}
					break;
				case CXM_COMMAND:
					printf("A command: ");
					switch(msgid)
					{
						case CXCMD_DISABLE:
						printf("CXCMD_DISABLE\n");
							ICommodities->ActivateCxObj(broker, 0L);
							break;
						case CXCMD_ENABLE:
							printf("CXCMD_ENABLE\n");
							ICommodities->ActivateCxObj(broker, 1L);
							break;
						case CXCMD_KILL:
							printf("CXCMD_KILL\n");
							returnvalue = 0L;
							break;
						case CXCMD_UNIQUE:
						/* Commodities Exchange can be told not only to refuse to launch a    */
						/* commodity with a name already in use but also can notify the       */
						/* already running commodity that it happened.  It does this by       */
						/* sending a CXM_COMMAND with the ID set to CXMCMD_UNIQUE.  If the    */
						/* user tries to run a windowless commodity that is already running,  */
						/* the user wants the commodity to shut down.                         */
							printf("CXCMD_UNIQUE\n");
							returnvalue = 0L;
							break;
						default:
							printf("Unknown msgid\n");
							break;
					}
					break;
				default:
					printf("Unknown msgtype\n");
					break;
			}
		}

		if (sigrcvd & SIGBREAKF_CTRL_C)
		{
			returnvalue = 0L;
			printf("CTRL C signal break\n");
		}
	}
}
AmigaOne X1000 with 2GB memory - OS4.1 FE
User avatar
trixie
Posts: 409
Joined: Thu Jun 30, 2011 2:54 pm
Location: Czech Republic

Re: Troubles in Commodity-land

Post by trixie »

@xenix

Great, I'll replace the old example in the wiki, once I finish this bottle of Islay Mist. Is it enough to mention "Adapted by xenic", or do you want your full name there?
The Rear Window blog

AmigaOne X5000 @ 2GHz / 4GB RAM / Radeon RX 560 / ESI Juli@ / AmigaOS 4.1 Final Edition
SAM440ep-flex @ 667MHz / 1GB RAM / Radeon 9250 / AmigaOS 4.1 Final Edition
xenic
Posts: 1185
Joined: Sun Jun 19, 2011 12:06 am

Re: Troubles in Commodity-land

Post by xenic »

trixie wrote:@xenix

Great, I'll replace the old example in the wiki, once I finish this bottle of Islay Mist. Is it enough to mention "Adapted by xenic", or do you want your full name there?
I would prefer that xenic be used.
When I copy code from these forums I get this error for every line: _PopShell.c :208: error: stray '\240' in program. If possible I would request that you check that the code you put in the WIKI is clean and compiles if copied from the WIKI. If you need the original unaltered code just give me an email address here or PM me with an address and I'll send it attached as an lha archive.
AmigaOne X1000 with 2GB memory - OS4.1 FE
chris
Posts: 562
Joined: Sat Jun 18, 2011 11:05 am
Contact:

Re: Troubles in Commodity-land

Post by chris »

xenic wrote:I use a lot of seperate screens and after I've iconified a program from a seperate screen to reduce screen crowding, I find it convenient to be able to reopen the iconified program with a hotkey rather than switching to the Workbench screen, clicking the icon and then returning to the screen I'm working on.
That's fair enough, however I'd argue this is exactly what the FKey commodity is for. It ideally needs to be expanded to contain some commands for "send application.library SHOW command to...", then there is no excuse for applications implementing their own global popup keys. However in the current incarnation you can put an ARexx command in to bring the application to the front.

This really needs to go into the style guide or something to stop it happening (or at least to make it easier to argue about!). "Do not install a global input handler without a very good reason". "Applications do not need global popup keys unless they are designed to be run hidden (ie. they are commodities)". "A web browser or email client is not a commodity!"
On the other hand, I can see how Commodities hotkey use can be abusive. I still use Turbotext which allows unlimited global hotkeys to be defined. I recently discovered why some hotkeys are unavailabe for "REAL" commodity use. Turbotext defines 5 global hotkeys in the default preferences. Ugh, bad idea; I need to get rid of those.
If those are hotkeys just for Turbotext, they should not be global. It should only be listening for keyboard commands when the window is active. If they are really global and there's no need for it, that is certainly bad practice. Too late to do anything about it now, but it brings me back to my style guide point.
chris
Posts: 562
Joined: Sat Jun 18, 2011 11:05 am
Contact:

Re: Troubles in Commodity-land

Post by chris »

trixie wrote:@chris
MUI registers everything as a commodity irrespective of what it actually is AFAIK. I'd certainly regard this as an abuse of the commodities framework
Me too (if it's really the case). Could abuse be any more blatant than this? :-)
According to the response on my bug report, it can be disabled, but this is the first I've heard of it (admittedly I've never done any MUI programming).
One of my other gripes is that "true applications" that install as commodities only to get a popup key shortcut don't bother to handle CXCMD_DISABLE and CXCMD_ENABLE because, quite logically, normal apps like a browser are not supposed to get activated or deactivated. So a commodities control program (and the user) will see the program as a running commodity but the control will look broken (the app is not responding to activation/deactivation commands). This I think can be confusing.
Yes, definitely something that can't be enabled/disabled is not a commodity.
What I've suggested in a post above is a system that "serves" CX events to applications that have "subscribed" to them. This way an application could receive a global hotkey event without actually registering as a commodity. It would make sense to implement such functionality on the application.library level.
Yes, application.library could register as a broker and process global hotkeys. I still think this should be discouraged, but at least that gets the functionality into application.library, unclutters Commodities Exchange and removes the excuse that "we have to register as a commodity because application.library doesn't support global popup hotkeys."
User avatar
tboeckel
AmigaOS Core Developer
AmigaOS Core Developer
Posts: 68
Joined: Mon Jun 20, 2011 8:56 am
Contact:

Re: Troubles in Commodity-land

Post by tboeckel »

chris wrote:but I can't really be bothered to argue about it and the bugtracker won't let me add to or re-open the bug anyway.
Did you try to login? Your account is approved. As such you are able to comment and to reopen tickets. But that requires a successfull login. Otherwise everything is forbidden or at least will require moderation by us. Lots of other persons have no problems to comment and to reopen tickets. I don't think you are an exception from the rule here.
Post Reply