Page 1 of 1

Hooks documentation

Posted: Tue Oct 11, 2011 8:58 pm
by JosDuchIt
I think i am on the verge of understanding hooks, but the least i can say is that some OS4 tutorial on this matter is badly needed(those registers you find in the docs just obscure things more)
The needed info is very dispersed in the RKRM plus the SDK docs.

I understand (now) that the arguments of hookfunctions you write, are filled in by the OS libraries. In the source i am working on it seemed that for a Windows backfill hook the structure of the third argument was defined as struct BackFill by the author, whereas the OS library uses BackFillMessage with exactly the same structure;
I was not able to find anywhere in the docs that the second
argument was of type struct Rastport.

The program below is a synthesis of the Gui4Cli source's approach.
It works but the reverse is not true, even after correcting the source in conformity with his smaller model, I get unhelpfull freezes immediately after loading with the Gui4Cli a (Gui4Cli)script that opens a window.
So i am still stuck in commenting out the WA_BackFill lines in OpenWindowTagList() call.
I am out of ideas how to tackle this. The last idea i had was to have the do_Backfill() function return immediately, but the behaviour is the same.

Code: Select all

/* compiles and works, use -lauto  */

#define __USE_INLINE__
#define __USE_BASETYPE__
#define ZERO ((BPTR)NULL)

#include <proto/intuition.h> //OpenWindowTags CloseWindow
#include <proto/graphics.h> //SetAPen SetDrMd SetMaxPen RectFill
#include <proto/dos.h> //Delay Printf
#include <proto/exec.h> //AllocSysObjectTags
#include <exec/types.h>
#include <exec/exec.h>
#include <exec/execbase.h>
#include <exec/ports.h>
#include <exec/io.h>
#include <intuition/intuition.h>




struct BackFillData //Michaël van Elst
{
	struct Layer *l;
	struct Rectangle bounds;
	LONG	 offx, offy;
};


/*graphics/layers.h
 * The message a backfill hook receives
 
struct BackFillMessage
{
    struct Layer     *Layer;
    struct Rectangle  Bounds;
    LONG              OffsetX;
    LONG              OffsetY;
};
*/ 

struct BackFill // michaël van Elst 
{
	char	 mode;	 /* s=solid, p=pattern, i=icon, I=image */
	SHORT	 apen, bpen;
	LONG	 top, left, width, height;
	struct DiskObject *dobj;
	struct BitMap BM;
	struct imginfo *img;
};

struct guifile
{
	struct BackFill bf;
	struct Remember *rkey;	
	struct Hook *hk;   //OS4 was 
	///struct Hook hk;
} *gf;

/*
struct Hook //proto/hooks.h
{
    struct MinNode  h_MinNode;
    ULONG         (*h_Entry)();    /* assembler entry point */
    ULONG         (*h_SubEntry)(); /* often HLL entry point */
    APTR            h_Data;        /* owner specific        */
}*/


/*struct Rectangle graphics/gfx.h
{   //redefinition of struct Rectangle
    WORD MinX;
    WORD MinY;
    WORD MaxX;
    WORD MaxY;
}; */
ULONG INTERRUPT SAVEDS do_backfill(struct Hook * , struct RastPort * , struct BackFillData * );

// where do we find that the 2de arg is struct Tastport *



ULONG INTERRUPT SAVEDS do_backfill(struct Hook *h, struct RastPort *rp, struct BackFillData *bfd)
{
struct RastPort clonerp;
struct BackFill *bf;

bf = (struct BackFill *)h->h_Data;

// *---------- Clone rastport -----------* /

clonerp = *rp;			  // * clone Rastport so as not to change user settings * /
clonerp.Layer = NULL;  // * Backfill RastPorts must not have a layer * /

// *---------- do backfill --------------* /
switch (bf->mode)
{
	case 's' : // SOLID
			SetAPen (&clonerp, bf->apen);
			SetDrMd (&clonerp, JAM1);
			SetMaxPen (&clonerp, ~0);				  // * V39 only * /

			RectFill (&clonerp, bfd->bounds.MinX, bfd->bounds.MinY,
					bfd->bounds.MaxX, bfd->bounds.MaxY);  //OS4E
			break;
}
return (0);
}
 

int main() {

  struct Window *myWindow;
  struct Remember *tempkey=NULL;
  struct guifile * gf;
 
  if (!(gf = (struct guifile *)AllocRemember(&tempkey, sizeof(struct guifile),
MEMF_CLEAR)))
  { goto endFUN;	 }
  gf->rkey = tempkey;
  tempkey = NULL;
  //APTR bfhook;
  gf->bf.apen = 4; //change backgroudn color here
  gf->bf.mode = 's';
  gf->bf.bpen = 2;
  //gf->bf.dobj = NULL;
  if (!(gf->hk=AllocSysObjectTags( ASOT_HOOK, ASOHOOK_Entry, do_backfill, ASOHOOK_Data, NULL, TAG_DONE)))
   { goto endFUN; }  
  gf->hk->h_Data = (APTR)&gf->bf; 


struct TagItem win_tags[] =
    {
    {WA_Left        , 20L          },
    {WA_Top         , 20L          },
    {WA_Width       , 200L         },
    {WA_Height      , 150L         },
    {WA_MinWidth    , 200L         },
	 {WA_MinHeight   , 100L         },
	 {WA_MaxWidth    , ~0           },
	 {WA_MaxHeight   , ~0           },
	 {WA_AutoAdjust  , TRUE         },
	 {WA_Activate    , TRUE         },
    {WA_Title       , (LONG)"My Window"  },
	 {WA_Flags       , WFLG_SIZEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET | WFLG_ACTIVATE },
	 {WA_BackFill    , (LONG)gf->hk },	
	 {WA_IDCMP       , ZERO         }, 
    {TAG_DONE       , ZERO         }, 
    };

  myWindow = OpenWindowTagList (NULL, win_tags);

  Delay(200);
  if (myWindow) CloseWindow(myWindow);
  FreeRemember(&gf->rkey, TRUE);
  return(0);
endFUN:
 return(1);
 
}

Re: Hooks documentation

Posted: Tue Oct 11, 2011 9:26 pm
by thomasrapp
I was not able to find anywhere in the docs that the second
argument was of type struct Rastport.
From the autodocs of layers.library/InstallLayerHook:

hook - pointer to layer callback Hook which will be called
with object == (struct RastPort *) result->RastPort
and message == [ (Layer *) layer, (struct Rectangle) bounds,
(LONG) offsetx, (LONG) offsety ]

This hook should fill the Rectangle in the RastPort
with the BackFill pattern appropriate for offset x/y.

If hook is LAYERS_BACKFILL, the default backfill is
used for the layer. (Same as pre-2.0)

As of V39:
If hook is LAYERS_NOBACKFILL, the layer will not be
backfilled (NO-OP).

If you didn't read the above you probably didn't read this, too:
NOTES
The RastPort you are passed back is the same one passed to the
function. You should *not* use "layered" rendering functions
on this RastPort. Generally, you will wish to do BitMap operations
such as BltBitMap(). The callback is a raw, low-level rendering
call-back. If you need to call a rendering operation with a
RastPort, make sure you use a copy of the RastPort and NULL the
Layer pointer.

BTW, I made a complete working backfill example for someone at utilitybase som time ago: http://thomas-rapp.homepage.t-online.de/examples/bf.lha
The reason why people define their own struct for the backfill message is that struct BackFillMessage didn't exist in NDK 3.9.

Re: Hooks documentation

Posted: Wed Oct 12, 2011 3:59 pm
by JosDuchIt
@thomasrapp
Thank you for the example. Looks very nice.

I did visit the page on which it is supposed to appear (it does not appear there) and found a lot of other interesting porgramming examples. I regret that in the past using google to find Amiga C example and snippets i never did find your page.

Now for the extracts of layers.doc concerning layers.library/InstallLayerHook : nowhere in the source, i am trying to make fully work under OS4, InstallLayerHook is used. It is not used in your example neither.
So the least one can say is that a programmer that just wants to add a nice background for his applicationwindow , discovering that you can do it with the OpenWindowTaglist function using WA_BackFill is not given the info needed where he should find it. These days getting hlp from (fewer) experienced programmers is harder than it has been in the past.
If they can spare some time to write tutorials, it is all but time lost to the community.

Re: Hooks documentation

Posted: Wed Oct 12, 2011 5:17 pm
by thomasrapp
So the least one can say is that a programmer that just wants to add a nice background for his applicationwindow , discovering that you can do it with the OpenWindowTaglist function using WA_BackFill is not given the info needed where he should find it.
Well, open autodocs/intuition.doc and search for wa_backfill. You'll find this in the chapter about OpenWindow:
WA_BackFill - ti_Data is a pointer to a Hook structure that
the Layers library will call when your window needs
"backfilling." See layers.library/InstallLayerHook().
And I am sure that the OpenWindowTags autodocs state that for a description of the tags you should refer to OpenWindow.

BTW, I should mention that yesterday after I completed my post here I copied your example and compiled it with GCC and it works. No lockups here. The only quirk was that you use nested comments which is not allowed in C. So I had to remove the comments in lines 61 thru 64 (struct Hook). After that it compiled without errors.

Re: Hooks documentation

Posted: Wed Oct 12, 2011 5:26 pm
by thomasrapp
even after correcting the source in conformity with his smaller model, I get unhelpfull freezes immediately after loading with the Gui4Cli a (Gui4Cli)script that opens a window.
So i am still stuck in commenting out the WA_BackFill lines in OpenWindowTagList() call.
I am out of ideas how to tackle this. The last idea i had was to have the do_Backfill() function return immediately, but the behaviour is the same.
This is difficult to debug without seeing the source.

A common mistake when working with pointers to structs in tag lists is the use of the & operand.

If you have a pointer to a hook like

struct Hook *hk = Alloc...

then you should use the pointer as in

WA_BackFill, hk

But if you have a struct Hook (like in my example)

struct Hook hk = {....};

then you need to supply a pointer to it

WA_Backfill, &hk

If you use &kh in the first example, it will crash as well as the second example if you use hk instead of &hk.