ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/video_x.cpp
(Generate patch)

Comparing BasiliskII/src/Unix/video_x.cpp (file contents):
Revision 1.50 by cebix, 2001-07-01T21:09:29Z vs.
Revision 1.51 by cebix, 2001-07-03T15:59:47Z

# Line 24 | Line 24
24   *      Ctrl-Tab = suspend DGA mode
25   *      Ctrl-Esc = emergency quit
26   *      Ctrl-F1 = mount floppy
27 + *      Ctrl-F5 = grab mouse (in windowed mode)
28   */
29  
30   #include "sysdeps.h"
# Line 73 | Line 74 | enum {
74   // Constants
75   const char KEYCODE_FILE_NAME[] = DATADIR "/keycodes";
76  
77 < static const int win_eventmask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | ExposureMask | StructureNotifyMask;
77 > static const int win_eventmask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ExposureMask | StructureNotifyMask;
78   static const int dga_eventmask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask;
79  
80  
# Line 322 | Line 323 | public:
323          virtual void update_palette(void);
324          virtual void suspend(void) {}
325          virtual void resume(void) {}
326 +        virtual void toggle_mouse_grab(void) {}
327 +        virtual void mouse_moved(int x, int y) { ADBMouseMoved(x, y); }
328 +
329 +        virtual void grab_mouse(void) {}
330 +        virtual void ungrab_mouse(void) {}
331  
332   public:
333          bool init_ok;   // Initialization succeeded (we can't use exceptions because of -fomit-frame-pointer)
# Line 342 | Line 348 | public:
348          driver_window(const video_mode &mode);
349          ~driver_window();
350  
351 +        void toggle_mouse_grab(void);
352 +        void mouse_moved(int x, int y);
353 +
354 +        void grab_mouse(void);
355 +        void ungrab_mouse(void);
356 +
357   private:
358          GC gc;
359          XImage *img;
360 <        bool have_shm;                          // Flag: SHM extensions available
360 >        bool have_shm;                                  // Flag: SHM extensions available
361          XShmSegmentInfo shminfo;
362          Cursor mac_cursor;
363 +        bool mouse_grabbed;                             // Flag: mouse pointer grabbed, using relative mouse mode
364 +        int mouse_last_x, mouse_last_y; // Last mouse position (for relative mode)
365   };
366  
367   static driver_base *drv = NULL; // Pointer to currently used driver object
# Line 365 | Line 379 | driver_base::driver_base()
379  
380   driver_base::~driver_base()
381   {
382 +        ungrab_mouse();
383 +
384          if (w) {
385                  XUnmapWindow(x_display, w);
386                  wait_unmapped(w);
# Line 421 | Line 437 | void driver_base::update_palette(void)
437  
438   // Open display
439   driver_window::driver_window(const video_mode &mode)
440 < : gc(0), img(NULL), have_shm(false), mac_cursor(0)
440 > : gc(0), img(NULL), have_shm(false), mouse_grabbed(false), mac_cursor(0)
441   {
442          int width = mode.x, height = mode.y;
443          int aligned_width = (width + 15) & ~15;
444          int aligned_height = (height + 15) & ~15;
445  
446          // Set absolute mouse mode
447 <        ADBSetRelMouseMode(false);
447 >        ADBSetRelMouseMode(mouse_grabbed);
448  
449          // Create window
450          XSetWindowAttributes wattr;
# Line 561 | Line 577 | driver_window::~driver_window()
577                  XFreeGC(x_display, gc);
578   }
579  
580 + // Toggle mouse grab
581 + void driver_window::toggle_mouse_grab(void)
582 + {
583 +        if (mouse_grabbed)
584 +                ungrab_mouse();
585 +        else
586 +                grab_mouse();
587 + }
588 +
589 + // Grab mouse, switch to relative mouse mode
590 + void driver_window::grab_mouse(void)
591 + {
592 +        int result;
593 +        for (int i=0; i<10; i++) {
594 +                result = XGrabPointer(x_display, w, True, 0,
595 +                        GrabModeAsync, GrabModeAsync, w, None, CurrentTime);
596 +                if (result != AlreadyGrabbed)
597 +                        break;
598 +                Delay_usec(100000);
599 +        }
600 +        if (result == GrabSuccess) {
601 +                ADBSetRelMouseMode(mouse_grabbed = true);
602 +                XStoreName(x_display, w, GetString(STR_WINDOW_TITLE_GRABBED));
603 +                XSync(x_display, false);
604 +        }
605 + }
606 +
607 + // Ungrab mouse, switch to absolute mouse mode
608 + void driver_window::ungrab_mouse(void)
609 + {
610 +        if (mouse_grabbed) {
611 +                XUngrabPointer(x_display, CurrentTime);
612 +                XStoreName(x_display, w, GetString(STR_WINDOW_TITLE));
613 +                ADBSetRelMouseMode(mouse_grabbed = false);
614 +        }
615 + }
616 +
617 + // Mouse moved
618 + void driver_window::mouse_moved(int x, int y)
619 + {
620 +        if (!mouse_grabbed) {
621 +                mouse_last_x = x; mouse_last_y = y;
622 +                ADBMouseMoved(x, y);
623 +                return;
624 +        }
625 +
626 +        // Warped mouse motion (this code is taken from SDL)
627 +
628 +        // Post first mouse event
629 +        int width = VideoMonitor.mode.x, height = VideoMonitor.mode.y;
630 +        int delta_x = x - mouse_last_x, delta_y = y - mouse_last_y;
631 +        mouse_last_x = x; mouse_last_y = y;
632 +        ADBMouseMoved(delta_x, delta_y);
633 +
634 +        // Only warp the pointer when it has reached the edge
635 +        const int MOUSE_FUDGE_FACTOR = 8;
636 +        if (x < MOUSE_FUDGE_FACTOR || x > (width - MOUSE_FUDGE_FACTOR)
637 +         || y < MOUSE_FUDGE_FACTOR || y > (height - MOUSE_FUDGE_FACTOR)) {
638 +                XEvent event;
639 +                while (XCheckTypedEvent(x_display, MotionNotify, &event)) {
640 +                        delta_x = x - mouse_last_x; delta_y = y - mouse_last_y;
641 +                        mouse_last_x = x; mouse_last_y = y;
642 +                        ADBMouseMoved(delta_x, delta_y);
643 +                }
644 +                mouse_last_x = width/2;
645 +                mouse_last_y = height/2;
646 +                XWarpPointer(x_display, None, w, 0, 0, 0, 0, mouse_last_x, mouse_last_y);
647 +                for (int i=0; i<10; i++) {
648 +                        XMaskEvent(x_display, PointerMotionMask, &event);
649 +                        if (event.xmotion.x > (mouse_last_x - MOUSE_FUDGE_FACTOR)
650 +                         && event.xmotion.x < (mouse_last_x + MOUSE_FUDGE_FACTOR)
651 +                         && event.xmotion.y > (mouse_last_y - MOUSE_FUDGE_FACTOR)
652 +                         && event.xmotion.y < (mouse_last_y + MOUSE_FUDGE_FACTOR))
653 +                                break;
654 +                }
655 +        }
656 + }
657 +
658  
659   #if defined(ENABLE_XF86_DGA) || defined(ENABLE_FBDEV_DGA)
660   /*
# Line 639 | Line 733 | void driver_dga::resume(void)
733          XMapRaised(x_display, w);
734          wait_mapped(w);
735          XWarpPointer(x_display, None, rootwin, 0, 0, 0, 0, 0, 0);
736 <        XGrabKeyboard(x_display, rootwin, 1, GrabModeAsync, GrabModeAsync, CurrentTime);
737 <        XGrabPointer(x_display, rootwin, 1, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
736 >        XGrabKeyboard(x_display, rootwin, True, GrabModeAsync, GrabModeAsync, CurrentTime);
737 >        XGrabPointer(x_display, rootwin, True, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
738   #ifdef ENABLE_XF86_DGA
739          XF86DGADirectVideo(x_display, screen, XF86DGADirectGraphics | XF86DGADirectKeyb | XF86DGADirectMouse);
740          XF86DGASetViewPort(x_display, screen, 0, 0);
# Line 1465 | Line 1559 | void video_set_palette(uint8 *pal, int n
1559          // Recalculate pixel color expansion map
1560          if (!IsDirectMode(VideoMonitor.mode) && (vis->c_class == TrueColor || vis->c_class == DirectColor)) {
1561                  for (int i=0; i<256; i++) {
1562 <                        int c = i % num_in; // If there are less than 256 colors, we repeat the first entries (this makes color expansion easier)
1562 >                        int c = i & (num_in-1); // If there are less than 256 colors, we repeat the first entries (this makes color expansion easier)
1563                          ExpandMap[i] = map_rgb(pal[c*3+0], pal[c*3+1], pal[c*3+2]);
1564                  }
1565  
# Line 1502 | Line 1596 | void video_switch_to_mode(const video_mo
1596  
1597  
1598   /*
1599 < *  Translate key event to Mac keycode
1599 > *  Translate key event to Mac keycode, returns -1 if no keycode was found
1600 > *  and -2 if the key was recognized as a hotkey
1601   */
1602  
1603 < static int kc_decode(KeySym ks)
1603 > static int kc_decode(KeySym ks, bool key_down)
1604   {
1605          switch (ks) {
1606                  case XK_A: case XK_a: return 0x00;
# Line 1558 | Line 1653 | static int kc_decode(KeySym ks)
1653                  case XK_period: case XK_greater: return 0x2f;
1654                  case XK_slash: case XK_question: return 0x2c;
1655  
1656 < #if defined(ENABLE_XF86_DGA) || defined(ENABLE_FBDEV_DGA)
1562 <                case XK_Tab: if (ctrl_down) {drv->suspend(); return -1;} else return 0x30;
1563 < #else
1564 <                case XK_Tab: return 0x30;
1565 < #endif
1656 >                case XK_Tab: if (ctrl_down) {if (key_down) drv->suspend(); return -2;} else return 0x30;
1657                  case XK_Return: return 0x24;
1658                  case XK_space: return 0x31;
1659                  case XK_BackSpace: return 0x33;
# Line 1596 | Line 1687 | static int kc_decode(KeySym ks)
1687                  case XK_Left: return 0x3b;
1688                  case XK_Right: return 0x3c;
1689  
1690 <                case XK_Escape: if (ctrl_down) {quit_full_screen = true; emerg_quit = true; return -1;} else return 0x35;
1690 >                case XK_Escape: if (ctrl_down) {if (key_down) { quit_full_screen = true; emerg_quit = true; } return -2;} else return 0x35;
1691  
1692 <                case XK_F1: if (ctrl_down) {SysMountFirstFloppy(); return -1;} else return 0x7a;
1692 >                case XK_F1: if (ctrl_down) {if (key_down) SysMountFirstFloppy(); return -2;} else return 0x7a;
1693                  case XK_F2: return 0x78;
1694                  case XK_F3: return 0x63;
1695                  case XK_F4: return 0x76;
1696 <                case XK_F5: return 0x60;
1696 >                case XK_F5: if (ctrl_down) {if (key_down) drv->toggle_mouse_grab(); return -2;} else return 0x60;
1697                  case XK_F6: return 0x61;
1698                  case XK_F7: return 0x62;
1699                  case XK_F8: return 0x64;
# Line 1650 | Line 1741 | static int kc_decode(KeySym ks)
1741          return -1;
1742   }
1743  
1744 < static int event2keycode(XKeyEvent &ev)
1744 > static int event2keycode(XKeyEvent &ev, bool key_down)
1745   {
1746          KeySym ks;
1656        int as;
1747          int i = 0;
1748  
1749          do {
1750                  ks = XLookupKeysym(&ev, i++);
1751 <                as = kc_decode(ks);
1752 <                if (as != -1)
1751 >                int as = kc_decode(ks, key_down);
1752 >                if (as >= 0)
1753 >                        return as;
1754 >                if (as == -2)
1755                          return as;
1756          } while (ks != NoSymbol);
1757  
# Line 1706 | Line 1798 | static void handle_events(void)
1798                          }
1799  
1800                          // Mouse moved
1709                        case EnterNotify:
1801                          case MotionNotify:
1802 <                                ADBMouseMoved(event.xmotion.x, event.xmotion.y);
1802 >                                drv->mouse_moved(event.xmotion.x, event.xmotion.y);
1803                                  break;
1804  
1805                          // Keyboard
1806                          case KeyPress: {
1807 <                                int code;
1807 >                                int code = -1;
1808                                  if (use_keycodes) {
1809 <                                        event2keycode(event.xkey);      // This is called to process the hotkeys
1810 <                                        code = keycode_table[event.xkey.keycode & 0xff];
1809 >                                        if (event2keycode(event.xkey, true) != -2)      // This is called to process the hotkeys
1810 >                                                code = keycode_table[event.xkey.keycode & 0xff];
1811                                  } else
1812 <                                        code = event2keycode(event.xkey);
1813 <                                if (code != -1) {
1812 >                                        code = event2keycode(event.xkey, true);
1813 >                                if (code >= 0) {
1814                                          if (!emul_suspended) {
1815                                                  if (code == 0x39) {     // Caps Lock pressed
1816                                                          if (caps_on) {
# Line 1741 | Line 1832 | static void handle_events(void)
1832                                  break;
1833                          }
1834                          case KeyRelease: {
1835 <                                int code;
1835 >                                int code = -1;
1836                                  if (use_keycodes) {
1837 <                                        event2keycode(event.xkey);      // This is called to process the hotkeys
1838 <                                        code = keycode_table[event.xkey.keycode & 0xff];
1837 >                                        if (event2keycode(event.xkey, false) != -2)     // This is called to process the hotkeys
1838 >                                                code = keycode_table[event.xkey.keycode & 0xff];
1839                                  } else
1840 <                                        code = event2keycode(event.xkey);
1841 <                                if (code != -1 && code != 0x39) {       // Don't propagate Caps Lock releases
1840 >                                        code = event2keycode(event.xkey, false);
1841 >                                if (code >= 0 && code != 0x39) {        // Don't propagate Caps Lock releases
1842                                          ADBKeyUp(code);
1843                                          if (code == 0x36)
1844                                                  ctrl_down = false;
# Line 2011 | Line 2102 | static void update_display_static(driver
2102  
2103   static inline void possibly_quit_dga_mode()
2104   {
2105 <        // Quit DGA mode if requested
2105 >        // Quit DGA mode if requested (something terrible has happened and we
2106 >        // want to give control back to the user)
2107          if (quit_full_screen) {
2108                  quit_full_screen = false;
2109                  delete drv;
# Line 2019 | Line 2111 | static inline void possibly_quit_dga_mod
2111          }
2112   }
2113  
2114 + static inline void possibly_ungrab_mouse()
2115 + {
2116 +        // Ungrab mouse if requested (something terrible has happened and we
2117 +        // want to give control back to the user)
2118 +        if (quit_full_screen) {
2119 +                quit_full_screen = false;
2120 +                if (drv)
2121 +                        drv->ungrab_mouse();
2122 +        }
2123 + }
2124 +
2125   static inline void handle_palette_changes(void)
2126   {
2127          LOCK_PALETTE;
# Line 2071 | Line 2174 | static void video_refresh_dga_vosf(void)
2174  
2175   static void video_refresh_window_vosf(void)
2176   {
2177 <        // Quit DGA mode if requested
2178 <        possibly_quit_dga_mode();
2177 >        // Ungrab mouse if requested
2178 >        possibly_ungrab_mouse();
2179          
2180          // Handle X events
2181          handle_events();
# Line 2096 | Line 2199 | static void video_refresh_window_vosf(vo
2199  
2200   static void video_refresh_window_static(void)
2201   {
2202 +        // Ungrab mouse if requested
2203 +        possibly_ungrab_mouse();
2204 +
2205          // Handle X events
2206          handle_events();
2207          
# Line 2112 | Line 2218 | static void video_refresh_window_static(
2218  
2219   static void video_refresh_window_dynamic(void)
2220   {
2221 +        // Ungrab mouse if requested
2222 +        possibly_ungrab_mouse();
2223 +
2224          // Handle X events
2225          handle_events();
2226          

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines