rainbow: LinuxFb: vt console switch support

git-svn-id: svn://ultimatepp.org/upp/trunk@3690 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
kohait 2011-07-22 09:07:53 +00:00
parent c0139840cd
commit 68a2f22a28
3 changed files with 167 additions and 95 deletions

View file

@ -42,9 +42,9 @@ int has_imps2(int fd);
int set_imps2(int fd, int b);
void dupkmap(int fd);
int readevents(int ms);
void handle_mouse();
void handle_keyboard();
void switchvt(int ii);
void SaveModKeys(dword keycode, dword pressed);
dword fbKEYtoK(dword keycode);

View file

@ -175,13 +175,9 @@ void handle_keyboard()
keyup = (buf[i] & 0x80)?(K_KEYUP):(0);
bool b;
//char c = ((!keyup)?'=':' ');
//fprintf(stderr, "KEY %c: <%c> (%X) [%X]\n", c, keycode, keycode, buf[i]);
SaveModKeys(keycode, !keyup);
//Ctrl+Alt+FN for vt switch ??
//we dont support both sides, fall back to left
switch(keycode)
{
case SCANCODE_RIGHTALT: keycode = SCANCODE_LEFTALT; break;
@ -190,11 +186,34 @@ void handle_keyboard()
}
dword uppcode = fbKEYtoK(keycode) | keyup;
//fprintf(stderr, "UPP: %X - %X\n", uppcode, q);
if(!keyup && uppcode == K_SPACE)
uppcode = 0; //prevent double send with unicode
//vtswitch
int vtck = uppcode & (K_DELTA | 0xFFFF);
switch(vtck) {
case K_F11:
case K_F12:
vtck -= 18; //dirty hack: after F10 doesnt come F11, see vgakeyboard.h
case K_F1:
case K_F2:
case K_F3:
case K_F4:
case K_F5:
case K_F6:
case K_F7:
case K_F8:
case K_F9:
case K_F10:
if(GetCtrl() && GetAlt()) {
int ii = vtck - K_F1 + 1;
if(!keyup)
switchvt(ii);
return;
}
}
//first, the upp keycode
if(uppcode)
b = Ctrl::DoKeyFB(uppcode, 1);
@ -208,47 +227,9 @@ void handle_keyboard()
}
//helper quit
#if _DD
static int ii = 0;
#endif
if(uppcode == (K_SHIFT_CTRL | K_ESCAPE)
#ifdef _DD
|| (++ii >= 100)
#endif
)
if(uppcode == (K_SHIFT_CTRL | K_ESCAPE))
Ctrl::EndSession();
}
}
//returns 0 if timeout, 1 for mouse, 2 for keyboard
//common for waitforevents and sleep
int readevents(int ms)
{
fd_set fdset;
int max_fd;
static struct timeval to;
to.tv_sec = ms / 1000;
to.tv_usec = ms % 1000 * 1000;
FD_ZERO(&fdset);
max_fd = 0;
if(mouse_fd >= 0) {
FD_SET(mouse_fd, &fdset);
if(max_fd < mouse_fd) max_fd = mouse_fd;
}
if(keyb_fd >= 0) {
FD_SET(keyb_fd, &fdset);
if(max_fd < keyb_fd) max_fd = keyb_fd;
}
if(select(max_fd+1, &fdset, NULL, NULL, &to) > 0) {
if(mouse_fd >= 0) {
if(FD_ISSET(mouse_fd, &fdset)) return 1;
}
if(keyb_fd >= 0) {
if(FD_ISSET(keyb_fd, &fdset)) return 2;
}
}
return 0;
}
END_UPP_NAMESPACE

View file

@ -21,52 +21,7 @@ dword mouseb = 0;
int keyb_fd = -1;
int cvt = -1;
void FBQuitSession()
{
Ctrl::EndSession();
}
int pend = 0;
bool FBIsWaitingEvent()
{
pend = readevents(0);
return pend > 0;
}
bool FBProcessEvent(bool *quit)
{
if(pend)
{
if(pend & 1) handle_mouse();
if(pend & 2) handle_keyboard();
pend = 0; //need to reset, since with repeated call is not updated here, would stuck
return true;
}
return false;
}
void FBSleep(int ms)
{
pend = readevents(ms); //interruptable sleep
//keep queue busy, see SDLFb/Win.cpp for why
//this indicates that some stuff is pending, returning true in FBProcessEvent
//while nothing is actually processed
pend |= 4;
}
void FBUpdate(const Rect& inv)
{
//FIXME accelerate
const ImageBuffer& framebuffer = Ctrl::GetFrameBuffer();
memcpy(fbp, ~framebuffer, framebuffer.GetLength() * sizeof(RGBA));
}
void FBFlush()
{
}
//
int oldvt;
struct termios oldtermios;
@ -120,6 +75,48 @@ int entervt()
return 0;
}
void switchvt_pre()
{
ioctl(keyb_fd, KDSETMODE, KD_TEXT);
ioctl(keyb_fd, VT_UNLOCKSWITCH, 1);
}
void switchvt_post()
{
ioctl(keyb_fd, VT_LOCKSWITCH, 1);
ioctl(keyb_fd, KDSETMODE, KD_GRAPHICS);
}
int switched_away = 0;
void switchvt(int ii)
{
struct vt_stat vtst;
/* Figure out whether or not we're switching to a new console */
if(ioctl(keyb_fd, VT_GETSTATE, &vtst) < 0)
{
fprintf(stderr, "Error: could not read tty state");
return;
}
if(ii == vtst.v_active)
return;
LLOG("trying to switch to VT " << ii);
GuiLock __;
switchvt_pre();
if(ioctl(keyb_fd, VT_ACTIVATE, ii) == 0) {
ioctl(keyb_fd, VT_WAITACTIVE, ii);
switched_away = 1;
return;
}
switchvt_post();
}
void leavevt()
{
if(oldmode < 0) return;
@ -141,6 +138,97 @@ void leavevt()
ioctl(keyb_fd, VT_ACTIVATE, oldvt);
}
int pend = 0;
//returns 0 if timeout, 1 for mouse, 2 for keyboard
//common for waitforevents and sleep
int readevents(int ms)
{
fd_set fdset;
int max_fd;
static struct timeval to;
to.tv_sec = ms / 1000;
to.tv_usec = ms % 1000 * 1000;
if(switched_away) {
struct vt_stat vtst;
GuiLock __;
if((ioctl(keyb_fd, VT_GETSTATE, &vtst) == 0) &&
vtst.v_active == cvt) {
switched_away = 0;
switchvt_post();
}
}
FD_ZERO(&fdset);
max_fd = 0;
if(mouse_fd >= 0) {
FD_SET(mouse_fd, &fdset);
if(max_fd < mouse_fd) max_fd = mouse_fd;
}
if(keyb_fd >= 0) {
FD_SET(keyb_fd, &fdset);
if(max_fd < keyb_fd) max_fd = keyb_fd;
}
if(select(max_fd+1, &fdset, NULL, NULL, &to) > 0) {
if(mouse_fd >= 0) {
if(FD_ISSET(mouse_fd, &fdset)) return 1;
}
if(keyb_fd >= 0) {
if(FD_ISSET(keyb_fd, &fdset)) return 2;
}
}
return 0;
}
//
void FBQuitSession()
{
Ctrl::EndSession();
}
bool FBIsWaitingEvent()
{
pend = readevents(0);
return pend > 0;
}
bool FBProcessEvent(bool *quit)
{
if(pend)
{
if(pend & 1) handle_mouse();
if(pend & 2) handle_keyboard();
pend = 0; //need to reset, since with repeated call is not updated here, would stuck
return true;
}
return false;
}
void FBSleep(int ms)
{
pend = readevents(ms); //interruptable sleep
//keep queue busy, see SDLFb/Win.cpp for why
//this indicates that some stuff is pending, returning true in FBProcessEvent
//while nothing is actually processed
pend |= 4;
}
void FBUpdate(const Rect& inv)
{
if(switched_away) return; //backdraw
//FIXME accelerate
const ImageBuffer& framebuffer = Ctrl::GetFrameBuffer();
memcpy(fbp, ~framebuffer, framebuffer.GetLength() * sizeof(RGBA));
}
void FBFlush()
{
}
void FBInit(const String& fbdevice)
{
Ctrl::InitFB();
@ -255,17 +343,20 @@ void FBInit(const String& fbdevice)
if(keyb_fd < 0) {
LLOG("Using already assigned VT, must not detach");
struct vt_stat vtstate;
struct vt_stat vtst;
keyb_fd = open("/dev/tty", O_RDWR);
if(ioctl(keyb_fd, VT_GETSTATE, &vtstate) < 0) {
if(ioctl(keyb_fd, VT_GETSTATE, &vtst) < 0) {
cvt = 0;
} else {
cvt = vtstate.v_active;
cvt = vtst.v_active;
}
}
if(cvt>0)
fprintf(stdout, "started on VT %d\n", cvt);
ASSERT(keyb_fd>=0);
oldmode = -1;