Input
One of the most important parts of using an operating system is being able to interact with it. TempleOS lets you access the mouse and keyboard. So let's get started!
Mouse Input
In TempleOS events are typeically accessed via the messaging mechanism. We can get the mouse
coordnates by the GetMsg
function while looking for MSG_MS_MOVE
. You can check for
a mouse click via MSG_MS_R_DOWN
or MSG_MS_R_DOWN
.
I64 x,y;
U0 DrawIt(CTask *t,CDC *dc) {
dc->color=RED;
GrRect(dc,x,y,100,100);
}
U0 Run() {
Fs->draw_it=&DrawIt;
I64 m,x2,y2;
while(TRUE) {
//Here we write into the memory address containing x2/y2 by getting
// the addresses of x2/y2 and GetMsg with write into the these addresses
// chaning their values
m=GetMsg(&x2,&y2,1<<MSG_MS_MOVE+1<<MSG_MS_R_DOWN);
if(m==MSG_MS_R_DOWN)
break;
x=x2;
y=y2;
Refresh;
}
}
Run;
Keyboard Input(1)
You can get keys much like mouse events in TempleOS using GetMsg
. But before
we dive into this we need to know how keys are transmitted. There are
- Charactors(letters/numbers/etc) and
- Scancodes(the raw keycode with modifier keys like Ctrl/Alt)
A charactor is typically what can get displayed on the screen,but scancodes are
the juicy stuff. If you press A
, the charactor will be 'A'
,but the scancode will
be the raw key code in the .u8
from your keyboard AND some flags.(You can turn a charactor into a
scancode via Char2ScanCode('A');
)
The flags here will tell you if you were holding down ALT,CTRL,SHIFT or other
fun buttons while you pressed. You can check for these flags with the &
operator.
A simple example looks like this
I64 x,y;
I64 color=GREEN;
U0 DrawIt(CTask*,CDC*dc) {
dc->color=color;
GrRect(dc,x,y,100,100);
dc->color=RED;
}
U0 Run() {
Fs->draw_it=&DrawIt;
I64 msg,sc,ch;
for(;TRUE;) {
if(ScanMsg(&ch,&sc,1<<MSG_KEY_UP|1<<MSG_KEY_DOWN)) {
//SCAN IS STORED IN FIRST 8 BITS OF sc
if(sc.u8[0]==SC_ESC) break;
if(sc.u8[0]==SC_CURSOR_UP) {
y-=3;
} else if(sc.u8[0]==SC_CURSOR_DOWN) {
y+=3;
} else if(sc.u8[0]==SC_CURSOR_LEFT) {
x-=3;
} else if(sc.u8[0]==SC_CURSOR_RIGHT) {
x+=3;
}
//WE USE THE & OPERATOR TO TEST IF THE FLAG BIT IS SET OR NOT
if(sc&SCF_CTRL)
color=RED;
else if(sc&SCF_SHIFT)
color=YELLOW;
else
color=GREEN;
} else {
//Wait for a frame to be rendered
Refresh;
}
}
}
Run;
Keyboard Input(2) Scancode Galore
Scancodes have a rigid format. Each byte in a scancdoe has a specific purpose.
The first byte is the most important and can be accessed via scancode.u8[0]
.
Byte | Meaning |
---|---|
0 | Scancode (SC_ESC,SC_CURSOR_LEFT) |
1 through 3 | Flags |
4 Repeat of byte 0 | |
5 through 7 | Repeat of bytes 1-3 |
The flags are plentiful and contain a bitmask. You can test for a flag by
bitwise ANDing with the scancode to test the bit is set(no need to use scancode.u8[xxx]
)
Flag | Meaning |
---|---|
SCF_KEY_UP | The key is being released |
SCF_SHIFT | The shift key is down. |
SCFCTRL | The control key is down. |
SCF_ALT | The alt key is down. |
SCF_CAPS | The caps key is active. |
SCF_NUM | The numlock key is active. |
SCF_SCROLL | The scrolllock key is active. |
SCF_MS_L_DOWN | Mouse left button is down. |
SCF_MS_R_DOWN | Mouse left button is down. |
SCF_NO_SHIFT | Shift is not active. |
Keyboard Input(3)Multiple keys at once
Sometimes you want to check if multiple keys are down at once. Luckily for
you TempleOS keeps a record of all down keys. It is a bitfield called kbd.down_bitmap
.
Each scancode is a bit and can tested via Bt(kbd.down_bitmap,scancode)
... Example time:
I64 x,y;
U0 DrawIt(CTask*,CDC*dc) {
dc->color=GREEN;
GrRect(dc,x,y,100,100);
}
U0 Run() {
Fs->draw_it=&DrawIt;
I64 msg,sc,ch;
for(;TRUE;) {
if(Bt(kbd.down_bitmap,SC_ESC)) break;
if(Bt(kbd.down_bitmap,SC_CURSOR_UP)) y-=3;
if(Bt(kbd.down_bitmap,SC_CURSOR_DOWN)) y+=3;
if(Bt(kbd.down_bitmap,SC_CURSOR_LEFT)) x-=3;
if(Bt(kbd.down_bitmap,SC_CURSOR_RIGHT)) x+=3;
//Wait for a frame to be rendered
Refresh;
}
}
Run;
Exit;