I try to make my own function to get pressed key but I get stuck :( and don't find exactly what I must do.
I know I must get an intuition message linked to my window (to not catch keys if my app window is not active)
I start with this :
int DBGetKey( void ){
struct IntuiMessage *mymsg;
struct Message *timerMsg;
struct Windows *window;
/* Should add here how to get the window handle) */
mymsg = (struct IntuiMessage *) IExec->GetMsg(window->UserPort);
uint32 Class = mymsg->Class;
but after this I don't know how to do ... The AmigaOS SDK does not contain any exemple on keyboard handle method .. In fact, the SDK does not contain enough samples and does not cover enough principles ...
Thank you. Fred
All we have to decide is what to do with the time that is given to us.
Look up IDCMP_VANILLAKEY in the ModifyIDCMP() Autodoc That's a case of adding IDCMP_VANILLAKEY to the WA_IDCMP tag and then catching the messages - the character is in the IntuiMessage code field IIRC.
If you need anything more advanced then you'll need to look at IDCMP_RAWKEY.
int main () {
struct Window *window = NULL;
int done = FALSE;
struct IntuiMessage *msg;
// open a window on the default public screen
window = IIntuition->OpenWindowTags(NULL,
WA_Left, 50,
WA_Top, 50,
WA_Width, 100,
WA_Height, 100,
WA_Flags, WFLG_CLOSEGADGET|WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_SIZEGADGET
|WFLG_NOCAREREFRESH,
WA_IDCMP, IDCMP_CLOSEWINDOW|IDCMP_RAWKEY|IDCMP_VANILLAKEY,
TAG_END);
if (!window) goto out;
while (!done) {
// use IExec->Wait() here if you need to wait on more than one signal
IExec->WaitPort(window->UserPort);
while (msg = (struct IntuiMessage *)IExec->GetMsg(window->UserPort)) {
switch (msg->Class) {
case IDCMP_CLOSEWINDOW:
// user pressed the close gadget
done = TRUE;
break;
case IDCMP_VANILLAKEY:
// user pressed a key
switch (msg->Code) {
case '\n':
IDOS->Printf("User pressed: lf (0x%02lx)\n", msg->Code);
break;
case '\r':
IDOS->Printf("User pressed: cr (0x%02lx)\n", msg->Code);
break;
case '\t':
IDOS->Printf("User pressed: tab (0x%02lx)\n", msg->Code);
break;
default:
IDOS->Printf("User pressed: '%lc' (0x%02lx)\n", msg->Code, msg->Code);
break;
}
break;
case IDCMP_RAWKEY:
// this key couldn't be converted into an ASCII code,
// so we get a raw key code instead
IDOS->Printf("User pressed: 0x%02lx\n", msg->Code);
break;
}
IExec->ReplyMsg((struct Message *)msg);
}
}
out:
IIntuition->CloseWindow(window);
return 0;
}
Save it as window.c and compile with: gcc -O2 -o window window.c -lauto
You should really try to get your hands on an AmigaDev Cd 2.1 (old CD which contained SDK for OS 3.5, but also tons of electronic documentation like Rom Kernel Manuals, Amiga Mail, etc.) this will give you some insight of the Amiga programming specifics. If you can't afford it, you can also read the CManual from Aminet but be aware that it's seriously outaded but the general philosophy will be there.
IDCMP are events you can instruct a window to notify you about (via an IntuiMessage), for example IDCMP_VANILLAKEY instruct the window to notify you when the user press a key.
I tried to adapt your sample to my opengl sample and I get a DSI error on running ... I'm sure I've made an error with pointers or it's maybe because the glutCreateWindow() does not return the window handle ?
Here are the var(s):
/* Variables globales*/
struct BasicSetupStruct{
int DisplayWIDTH, DisplayHEIGHT, DisplayDEPTH;
int WindowID;
char WindowTitle[256];
BOOL IsFullSCREEN;
int RGBMode;
};
struct BasicSetupStruct BasicSetup;
int mywindow ;
struct Window *window = NULL;
struct IntuiMessage *msg;
Here is the window setup code :
/* Cr?ation de la fen?tre d'affichage principale */
void SetDisplayMode( int Width, int Height, int Depth ){
BOOL Supported;
int DMode = 0;
/* Supported = mglScreenModeIsSupported( Width, Height, Depth ); */
Supported = TRUE;
if ( Supported ){
/* Open the screen using windowed mode */
switch( Depth ){
case 8:
DMode = GL_COLOR_INDEX ;
break;
case 16:
case 24:
DMode = GLUT_RGB | GLUT_DEPTH ;
break;
case 32:
DMode = GLUT_RGBA | GLUT_DEPTH ;
break;
default:
DMode = GLUT_RGB | GLUT_DEPTH ;
}
BasicSetup.RGBMode = Depth;
glutInitDisplayMode( DMode ); /* Define display mode properties */
glutInitWindowSize( Width, Height );
BasicSetup.DisplayWIDTH = Width;
BasicSetup.DisplayHEIGHT = Height;
BasicSetup.DisplayDEPTH = Depth;
glutInitWindowPosition( 32, 32 );
BasicSetup.WindowTitle[0] = "AmiDARK Basic Test Application";
mywindow = glutCreateWindow( "AmiDARK Basic Test Application" ); /* Create the asked window */
window = &mywindow;
BasicSetup.WindowID = &mywindow;
if ( BasicSetup.IsFullSCREEN ){
glutGameModeString( "640x480:32" );
glutEnterGameMode();
}
}
}
And the function to check window close/key:
BOOL DBLoop(){
int done = FALSE;
struct IntuiMessage *msg;
// use IExec->Wait() here if you need to wait on more than one signal
msg = (struct IntuiMessage *)IExec->GetMsg(window->UserPort);
switch (msg->Class) {
case IDCMP_CLOSEWINDOW:
// user pressed the close gadget
done = TRUE;
break;
case IDCMP_VANILLAKEY:
// user pressed a key
switch (msg->Code) {
case '\n':
IDOS->Printf("User pressed: lf (0x%02lx)\n", msg->Code);
break;
case '\r':
IDOS->Printf("User pressed: cr (0x%02lx)\n", msg->Code);
break;
case '\t':
IDOS->Printf("User pressed: tab (0x%02lx)\n", msg->Code);
break;
default:
IDOS->Printf("User pressed: '%lc' (0x%02lx)\n", msg->Code, msg->Code);
break;
}
break;
case IDCMP_RAWKEY:
// this key couldn't be converted into an ASCII code,
// so we get a raw key code instead
IDOS->Printf("User pressed: 0x%02lx\n", msg->Code);
break;
}
IExec->ReplyMsg((struct Message *)msg);
return done;
}
I'm sur it's "mywindow" or "glutCreateWindow" that cause this but don't know how to fix this ... If I don't call DBLoop(), I don't get the crash and the program run well...
All we have to decide is what to do with the time that is given to us.
GetMsg() can return a NULL pointer thus is this case your line
switch (msg->Class) {
is trying to access the struct member Class from NULL pointer -> Crash.
GetMsg() only returns an IntuiMessage where there is one for you, if there aren't any you'll get a NULL pointer. Changing your code to
BOOL DBLoop(){
int done = FALSE;
struct IntuiMessage *msg;
// use IExec->Wait() here if you need to wait on more than one signal
msg = (struct IntuiMessage *)IExec->GetMsg(window->UserPort);
if( msg ) {
switch (msg->Class) {
case IDCMP_CLOSEWINDOW:
// user pressed the close gadget
done = TRUE;
break;
case IDCMP_VANILLAKEY:
// user pressed a key
switch (msg->Code) {
case '\n':
IDOS->Printf("User pressed: lf (0x%02lx)\n", msg->Code);
break;
case '\r':
IDOS->Printf("User pressed: cr (0x%02lx)\n", msg->Code);
break;
case '\t':
IDOS->Printf("User pressed: tab (0x%02lx)\n", msg->Code);
break;
default:
IDOS->Printf("User pressed: '%lc' (0x%02lx)\n", msg->Code, msg->Code);
break;
}
break;
case IDCMP_RAWKEY:
// this key couldn't be converted into an ASCII code,
// so we get a raw key code instead
IDOS->Printf("User pressed: 0x%02lx\n", msg->Code);
break;
}
IExec->ReplyMsg((struct Message *)msg);
}
return done;
}
//... int mywindow ; struct Window *window = NULL; //... mywindow = glutCreateWindow( "AmiDARK Basic Test Application" ); /* Create the asked window */ window = &mywindow; //...
What makes you think you can take a pointer to a glut window handle (int *) and pass it off as an intuition window handle (struct Window *)?
Either you use intuition to create your window and ignore glut entirely, or you use glut and use its callbacks for event handling, but don't try mixing glut and intuition because it won't work.
@salass00: But I must find a solution to use glut capabilities like I do without using the glutMainLoop() function ... So I must find a way to get keyboard entries using glut but not glutKeyboardFunc().
@abalaban: I've found my Developer CD OS 3.5 :p I will investigate on it but I doubt it cover OpenGL/GLUT ...
EDIT : I think I will restart my project from beginning without including OpenGL and when I'll start 3D, I'll incorporate OpenGL/MiniGL/Glut ... Do you think it's a better idea ?
Edited by freddix on 2009/3/20 15:05:18 Edited by freddix on 2009/3/20 15:25:25
All we have to decide is what to do with the time that is given to us.
@Chris with that I am obliged to encapsulate all my keyboards test within 1 function and for the need of my project I can't ... and this Keyboard() function is only called if I use the glutMainLoop() function and it's something I CAN'T USE for the needs of the project specificity.
All we have to decide is what to do with the time that is given to us.
@xeron I think you haven't understood the problem. To have this function to work I must call glutMainLoop() and main loop function and others (like keyboard ones) are executed. But I DON'T WANT THIS ! I don't use glutMainLoop() so, glut cannot send to the keyboard function the informations ... this function you provided is then useless ... Do you understand now ?
All we have to decide is what to do with the time that is given to us.