diff --git a/rainbow/LinuxFb/LinuxFbLocal.h b/rainbow/LinuxFb/LinuxFbLocal.h index a636902db..595f90c1b 100644 --- a/rainbow/LinuxFb/LinuxFbLocal.h +++ b/rainbow/LinuxFb/LinuxFbLocal.h @@ -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); diff --git a/rainbow/LinuxFb/Proc.cpp b/rainbow/LinuxFb/Proc.cpp index e8118b2a8..5ed8b86f7 100644 --- a/rainbow/LinuxFb/Proc.cpp +++ b/rainbow/LinuxFb/Proc.cpp @@ -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 diff --git a/rainbow/LinuxFb/Win.cpp b/rainbow/LinuxFb/Win.cpp index 7a0485251..a13e7aa10 100644 --- a/rainbow/LinuxFb/Win.cpp +++ b/rainbow/LinuxFb/Win.cpp @@ -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;