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.53 by cebix, 2001-07-06T20:49:53Z

# 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 36 | Line 37
37   #include <sys/shm.h>
38   #include <errno.h>
39  
40 + #include <algorithm>
41 +
42 + #ifndef NO_STD_NAMESPACE
43 + using std::sort;
44 + #endif
45 +
46   #ifdef HAVE_PTHREADS
47   # include <pthread.h>
48   #endif
# Line 73 | Line 80 | enum {
80   // Constants
81   const char KEYCODE_FILE_NAME[] = DATADIR "/keycodes";
82  
83 < static const int win_eventmask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | ExposureMask | StructureNotifyMask;
83 > static const int win_eventmask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ExposureMask | StructureNotifyMask;
84   static const int dga_eventmask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask;
85  
86  
# Line 115 | Line 122 | static int keycode_table[256];                                         // X
122  
123   // X11 variables
124   static int screen;                                                                      // Screen number
118 static int xdepth;                                                                      // Depth of X screen
125   static Window rootwin;                                                          // Root window and our window
126 < static XVisualInfo visualInfo;
127 < static Visual *vis;
122 < static Colormap cmap[2] = {0, 0};                                       // Colormaps for indexed modes (DGA needs two of them)
126 > static int num_depths = 0;                                                      // Number of available X depths
127 > static int *avail_depths = NULL;                                        // List of available X depths
128   static XColor black, white;
129   static unsigned long black_pixel, white_pixel;
130   static int eventmask;
131  
132 + static int xdepth;                                                                      // Depth of X screen
133 + static XVisualInfo visualInfo;
134 + static Visual *vis;
135 + static int color_class;
136 +
137   static int rshift, rloss, gshift, gloss, bshift, bloss; // Pixel format of DirectColor/TrueColor modes
138  
139 + static Colormap cmap[2] = {0, 0};                                       // Colormaps for indexed modes (DGA needs two of them)
140 +
141   static XColor palette[256];                                                     // Color palette to be used as CLUT and gamma table
142   static bool palette_changed = false;                            // Flag: Palette changed, redraw thread must set new colors
143  
# Line 191 | Line 203 | static inline uint32 map_rgb(uint8 red,
203          return ((red >> rloss) << rshift) | ((green >> gloss) << gshift) | ((blue >> bloss) << bshift);
204   }
205  
206 + // Do we have a visual for handling the specified Mac depth? If so, set the
207 + // global variables "xdepth", "visualInfo", "vis" and "color_class".
208 + static bool find_visual_for_depth(video_depth depth)
209 + {
210 +        D(bug("have_visual_for_depth(%d)\n", 1 << depth));
211 +
212 +        // Calculate minimum and maximum supported X depth
213 +        int min_depth = 1, max_depth = 32;
214 +        switch (depth) {
215 +                case VDEPTH_1BIT:       // 1-bit works always
216 +                        min_depth = 1;
217 +                        max_depth = 32;
218 +                        break;
219 + #ifdef ENABLE_VOSF
220 +                case VDEPTH_2BIT:
221 +                case VDEPTH_4BIT:       // VOSF blitters can convert 2/4-bit -> 16/32-bit
222 +                        min_depth = 15;
223 +                        max_depth = 32;
224 +                        break;
225 +                case VDEPTH_8BIT:       // VOSF blitters can convert 8-bit -> 16/32-bit
226 +                        min_depth = 8;
227 +                        max_depth = 32;
228 +                        break;
229 + #else
230 +                case VDEPTH_2BIT:
231 +                case VDEPTH_4BIT:       // 2/4-bit requires VOSF blitters
232 +                        return false;
233 +                case VDEPTH_8BIT:       // 8-bit without VOSF requires an 8-bit visual
234 +                        min_depth = 8;
235 +                        max_depth = 8;
236 +                        break;
237 + #endif
238 +                case VDEPTH_16BIT:      // 16-bit requires a 15/16-bit visual
239 +                        min_depth = 15;
240 +                        max_depth = 16;
241 +                        break;
242 +                case VDEPTH_32BIT:      // 32-bit requires a 24/32-bit visual
243 +                        min_depth = 24;
244 +                        max_depth = 32;
245 +                        break;
246 +        }
247 +        D(bug(" minimum required X depth is %d, maximum supported X depth is %d\n", min_depth, max_depth));
248 +
249 +        // Try to find a visual for one of the color depths
250 +        bool visual_found = false;
251 +        for (int i=0; i<num_depths && !visual_found; i++) {
252 +
253 +                xdepth = avail_depths[i];
254 +                D(bug(" trying to find visual for depth %d\n", xdepth));
255 +                if (xdepth < min_depth || xdepth > max_depth)
256 +                        continue;
257 +
258 +                // Determine best color class for this depth
259 +                switch (xdepth) {
260 +                        case 1: // Try StaticGray or StaticColor
261 +                                if (XMatchVisualInfo(x_display, screen, xdepth, StaticGray, &visualInfo)
262 +                                 || XMatchVisualInfo(x_display, screen, xdepth, StaticColor, &visualInfo))
263 +                                        visual_found = true;
264 +                                break;
265 +                        case 8: // Need PseudoColor
266 +                                if (XMatchVisualInfo(x_display, screen, xdepth, PseudoColor, &visualInfo))
267 +                                        visual_found = true;
268 +                                break;
269 +                        case 15:
270 +                        case 16:
271 +                        case 24:
272 +                        case 32: // Try DirectColor first, as this will allow gamma correction
273 +                                if (XMatchVisualInfo(x_display, screen, xdepth, DirectColor, &visualInfo)
274 +                                 || XMatchVisualInfo(x_display, screen, xdepth, TrueColor, &visualInfo))
275 +                                        visual_found = true;
276 +                                break;
277 +                        default:
278 +                                D(bug("  not a supported depth\n"));
279 +                                break;
280 +                }
281 +        }
282 +        if (!visual_found)
283 +                return false;
284 +
285 +        // Visual was found
286 +        vis = visualInfo.visual;
287 +        color_class = visualInfo.c_class;
288 +        D(bug(" found visual ID 0x%02x, depth %d, class ", visualInfo.visualid, xdepth));
289 + #if DEBUG
290 +        switch (color_class) {
291 +                case StaticGray: D(bug("StaticGray\n")); break;
292 +                case GrayScale: D(bug("GrayScale\n")); break;
293 +                case StaticColor: D(bug("StaticColor\n")); break;
294 +                case PseudoColor: D(bug("PseudoColor\n")); break;
295 +                case TrueColor: D(bug("TrueColor\n")); break;
296 +                case DirectColor: D(bug("DirectColor\n")); break;
297 +        }
298 + #endif
299 + }
300 +
301   // Add mode to list of supported modes
302   static void add_mode(uint32 width, uint32 height, uint32 resolution_id, uint32 bytes_per_row, video_depth depth)
303   {
# Line 322 | Line 429 | public:
429          virtual void update_palette(void);
430          virtual void suspend(void) {}
431          virtual void resume(void) {}
432 +        virtual void toggle_mouse_grab(void) {}
433 +        virtual void mouse_moved(int x, int y) { ADBMouseMoved(x, y); }
434 +
435 +        virtual void grab_mouse(void) {}
436 +        virtual void ungrab_mouse(void) {}
437  
438   public:
439          bool init_ok;   // Initialization succeeded (we can't use exceptions because of -fomit-frame-pointer)
# Line 342 | Line 454 | public:
454          driver_window(const video_mode &mode);
455          ~driver_window();
456  
457 +        void toggle_mouse_grab(void);
458 +        void mouse_moved(int x, int y);
459 +
460 +        void grab_mouse(void);
461 +        void ungrab_mouse(void);
462 +
463   private:
464          GC gc;
465          XImage *img;
466 <        bool have_shm;                          // Flag: SHM extensions available
466 >        bool have_shm;                                  // Flag: SHM extensions available
467          XShmSegmentInfo shminfo;
468          Cursor mac_cursor;
469 +        bool mouse_grabbed;                             // Flag: mouse pointer grabbed, using relative mouse mode
470 +        int mouse_last_x, mouse_last_y; // Last mouse position (for relative mode)
471   };
472  
473   static driver_base *drv = NULL; // Pointer to currently used driver object
# Line 365 | Line 485 | driver_base::driver_base()
485  
486   driver_base::~driver_base()
487   {
488 +        ungrab_mouse();
489 +
490          if (w) {
491                  XUnmapWindow(x_display, w);
492                  wait_unmapped(w);
# Line 406 | Line 528 | void driver_base::update_palette(void)
528                  int num = 256;
529                  if (IsDirectMode(VideoMonitor.mode))
530                          num = vis->map_entries; // Palette is gamma table
531 <                else if (vis->c_class == DirectColor)
531 >                else if (color_class == DirectColor)
532                          return; // Indexed mode on true color screen, don't set CLUT
533                  XStoreColors(x_display, cmap[0], palette, num);
534                  XStoreColors(x_display, cmap[1], palette, num);
# Line 421 | Line 543 | void driver_base::update_palette(void)
543  
544   // Open display
545   driver_window::driver_window(const video_mode &mode)
546 < : gc(0), img(NULL), have_shm(false), mac_cursor(0)
546 > : gc(0), img(NULL), have_shm(false), mouse_grabbed(false), mac_cursor(0)
547   {
548          int width = mode.x, height = mode.y;
549          int aligned_width = (width + 15) & ~15;
550          int aligned_height = (height + 15) & ~15;
551  
552          // Set absolute mouse mode
553 <        ADBSetRelMouseMode(false);
553 >        ADBSetRelMouseMode(mouse_grabbed);
554  
555          // Create window
556          XSetWindowAttributes wattr;
557          wattr.event_mask = eventmask = win_eventmask;
558          wattr.background_pixel = black_pixel;
559 <        wattr.colormap = (mode.depth == VDEPTH_1BIT && vis->c_class == PseudoColor ? DefaultColormap(x_display, screen) : cmap[0]);
559 >        wattr.colormap = (mode.depth == VDEPTH_1BIT && color_class == PseudoColor ? DefaultColormap(x_display, screen) : cmap[0]);
560          w = XCreateWindow(x_display, rootwin, 0, 0, width, height, 0, xdepth,
561 <                InputOutput, vis, CWEventMask | CWBackPixel | (vis->c_class == PseudoColor || vis->c_class == DirectColor ? CWColormap : 0), &wattr);
561 >                InputOutput, vis, CWEventMask | CWBackPixel | (color_class == PseudoColor || color_class == DirectColor ? CWColormap : 0), &wattr);
562  
563          // Set window name/class
564          set_window_name(w, STR_WINDOW_TITLE);
# Line 561 | Line 683 | driver_window::~driver_window()
683                  XFreeGC(x_display, gc);
684   }
685  
686 + // Toggle mouse grab
687 + void driver_window::toggle_mouse_grab(void)
688 + {
689 +        if (mouse_grabbed)
690 +                ungrab_mouse();
691 +        else
692 +                grab_mouse();
693 + }
694 +
695 + // Grab mouse, switch to relative mouse mode
696 + void driver_window::grab_mouse(void)
697 + {
698 +        int result;
699 +        for (int i=0; i<10; i++) {
700 +                result = XGrabPointer(x_display, w, True, 0,
701 +                        GrabModeAsync, GrabModeAsync, w, None, CurrentTime);
702 +                if (result != AlreadyGrabbed)
703 +                        break;
704 +                Delay_usec(100000);
705 +        }
706 +        if (result == GrabSuccess) {
707 +                ADBSetRelMouseMode(mouse_grabbed = true);
708 +                XStoreName(x_display, w, GetString(STR_WINDOW_TITLE_GRABBED));
709 +                XSync(x_display, false);
710 +        }
711 + }
712 +
713 + // Ungrab mouse, switch to absolute mouse mode
714 + void driver_window::ungrab_mouse(void)
715 + {
716 +        if (mouse_grabbed) {
717 +                XUngrabPointer(x_display, CurrentTime);
718 +                XStoreName(x_display, w, GetString(STR_WINDOW_TITLE));
719 +                ADBSetRelMouseMode(mouse_grabbed = false);
720 +        }
721 + }
722 +
723 + // Mouse moved
724 + void driver_window::mouse_moved(int x, int y)
725 + {
726 +        if (!mouse_grabbed) {
727 +                mouse_last_x = x; mouse_last_y = y;
728 +                ADBMouseMoved(x, y);
729 +                return;
730 +        }
731 +
732 +        // Warped mouse motion (this code is taken from SDL)
733 +
734 +        // Post first mouse event
735 +        int width = VideoMonitor.mode.x, height = VideoMonitor.mode.y;
736 +        int delta_x = x - mouse_last_x, delta_y = y - mouse_last_y;
737 +        mouse_last_x = x; mouse_last_y = y;
738 +        ADBMouseMoved(delta_x, delta_y);
739 +
740 +        // Only warp the pointer when it has reached the edge
741 +        const int MOUSE_FUDGE_FACTOR = 8;
742 +        if (x < MOUSE_FUDGE_FACTOR || x > (width - MOUSE_FUDGE_FACTOR)
743 +         || y < MOUSE_FUDGE_FACTOR || y > (height - MOUSE_FUDGE_FACTOR)) {
744 +                XEvent event;
745 +                while (XCheckTypedEvent(x_display, MotionNotify, &event)) {
746 +                        delta_x = x - mouse_last_x; delta_y = y - mouse_last_y;
747 +                        mouse_last_x = x; mouse_last_y = y;
748 +                        ADBMouseMoved(delta_x, delta_y);
749 +                }
750 +                mouse_last_x = width/2;
751 +                mouse_last_y = height/2;
752 +                XWarpPointer(x_display, None, w, 0, 0, 0, 0, mouse_last_x, mouse_last_y);
753 +                for (int i=0; i<10; i++) {
754 +                        XMaskEvent(x_display, PointerMotionMask, &event);
755 +                        if (event.xmotion.x > (mouse_last_x - MOUSE_FUDGE_FACTOR)
756 +                         && event.xmotion.x < (mouse_last_x + MOUSE_FUDGE_FACTOR)
757 +                         && event.xmotion.y > (mouse_last_y - MOUSE_FUDGE_FACTOR)
758 +                         && event.xmotion.y < (mouse_last_y + MOUSE_FUDGE_FACTOR))
759 +                                break;
760 +                }
761 +        }
762 + }
763 +
764  
765   #if defined(ENABLE_XF86_DGA) || defined(ENABLE_FBDEV_DGA)
766   /*
# Line 639 | Line 839 | void driver_dga::resume(void)
839          XMapRaised(x_display, w);
840          wait_mapped(w);
841          XWarpPointer(x_display, None, rootwin, 0, 0, 0, 0, 0, 0);
842 <        XGrabKeyboard(x_display, rootwin, 1, GrabModeAsync, GrabModeAsync, CurrentTime);
843 <        XGrabPointer(x_display, rootwin, 1, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
842 >        XGrabKeyboard(x_display, rootwin, True, GrabModeAsync, GrabModeAsync, CurrentTime);
843 >        XGrabPointer(x_display, rootwin, True, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
844   #ifdef ENABLE_XF86_DGA
845          XF86DGADirectVideo(x_display, screen, XF86DGADirectGraphics | XF86DGADirectKeyb | XF86DGADirectMouse);
846          XF86DGASetViewPort(x_display, screen, 0, 0);
# Line 1045 | Line 1245 | static void keycode_init(void)
1245   // Open display for specified mode
1246   static bool video_open(const video_mode &mode)
1247   {
1248 +        // Find best available X visual
1249 +        if (!find_visual_for_depth(mode.depth)) {
1250 +                ErrorAlert(STR_NO_XVISUAL_ERR);
1251 +                return false;
1252 +        }
1253 +
1254 +        // Create color maps
1255 +        if (color_class == PseudoColor || color_class == DirectColor) {
1256 +                cmap[0] = XCreateColormap(x_display, rootwin, vis, AllocAll);
1257 +                cmap[1] = XCreateColormap(x_display, rootwin, vis, AllocAll);
1258 +        }
1259 +
1260 +        // Find pixel format of direct modes
1261 +        if (color_class == DirectColor || color_class == TrueColor) {
1262 +                rshift = gshift = bshift = 0;
1263 +                rloss = gloss = bloss = 8;
1264 +                uint32 mask;
1265 +                for (mask=vis->red_mask; !(mask&1); mask>>=1)
1266 +                        ++rshift;
1267 +                for (; mask&1; mask>>=1)
1268 +                        --rloss;
1269 +                for (mask=vis->green_mask; !(mask&1); mask>>=1)
1270 +                        ++gshift;
1271 +                for (; mask&1; mask>>=1)
1272 +                        --gloss;
1273 +                for (mask=vis->blue_mask; !(mask&1); mask>>=1)
1274 +                        ++bshift;
1275 +                for (; mask&1; mask>>=1)
1276 +                        --bloss;
1277 +        }
1278 +
1279 +        // Preset palette pixel values for gamma table
1280 +        if (color_class == DirectColor) {
1281 +                int num = vis->map_entries;
1282 +                for (int i=0; i<num; i++) {
1283 +                        int c = (i * 256) / num;
1284 +                        palette[i].pixel = map_rgb(c, c, c);
1285 +                }
1286 +        }
1287 +
1288          // Load gray ramp to color map
1289 <        int num = (vis->c_class == DirectColor ? vis->map_entries : 256);
1289 >        int num = (color_class == DirectColor ? vis->map_entries : 256);
1290          for (int i=0; i<num; i++) {
1291                  int c = (i * 256) / num;
1292                  palette[i].red = c * 0x0101;
1293                  palette[i].green = c * 0x0101;
1294                  palette[i].blue = c * 0x0101;
1295 <                if (vis->c_class == PseudoColor)
1295 >                if (color_class == PseudoColor)
1296                          palette[i].pixel = i;
1297                  palette[i].flags = DoRed | DoGreen | DoBlue;
1298          }
# Line 1063 | Line 1303 | static bool video_open(const video_mode
1303  
1304   #ifdef ENABLE_VOSF
1305          // Load gray ramp to 8->16/32 expand map
1306 <        if (!IsDirectMode(mode) && (vis->c_class == TrueColor || vis->c_class == DirectColor))
1306 >        if (!IsDirectMode(mode) && (color_class == TrueColor || color_class == DirectColor))
1307                  for (int i=0; i<256; i++)
1308                          ExpandMap[i] = map_rgb(i, i, i);
1309   #endif
# Line 1155 | Line 1395 | bool VideoInit(bool classic)
1395          // Find screen and root window
1396          screen = XDefaultScreen(x_display);
1397          rootwin = XRootWindow(x_display, screen);
1398 <        
1399 <        // Get screen depth
1400 <        xdepth = DefaultDepth(x_display, screen);
1398 >
1399 >        // Get sorted list of available depths
1400 >        avail_depths = XListDepths(x_display, screen, &num_depths);
1401 >        if (avail_depths == NULL) {
1402 >                ErrorAlert(STR_UNSUPP_DEPTH_ERR);
1403 >                return false;
1404 >        }
1405 >        sort(avail_depths, avail_depths + num_depths);
1406          
1407   #ifdef ENABLE_FBDEV_DGA
1408          // Frame buffer name
# Line 1197 | Line 1442 | bool VideoInit(bool classic)
1442          black_pixel = BlackPixel(x_display, screen);
1443          white_pixel = WhitePixel(x_display, screen);
1444  
1200        // Get appropriate visual
1201        int color_class;
1202        switch (xdepth) {
1203                case 1:
1204                        color_class = StaticGray;
1205                        break;
1206                case 8:
1207                        color_class = PseudoColor;
1208                        break;
1209                case 15:
1210                case 16:
1211                case 24:
1212                case 32: // Try DirectColor first, as this will allow gamma correction
1213                        color_class = DirectColor;
1214                        if (!XMatchVisualInfo(x_display, screen, xdepth, color_class, &visualInfo))
1215                                color_class = TrueColor;
1216                        break;
1217                default:
1218                        ErrorAlert(STR_UNSUPP_DEPTH_ERR);
1219                        return false;
1220        }
1221        if (!XMatchVisualInfo(x_display, screen, xdepth, color_class, &visualInfo)) {
1222                ErrorAlert(STR_NO_XVISUAL_ERR);
1223                return false;
1224        }
1225        if (visualInfo.depth != xdepth) {
1226                ErrorAlert(STR_NO_XVISUAL_ERR);
1227                return false;
1228        }
1229        vis = visualInfo.visual;
1230
1231        // Create color maps
1232        if (color_class == PseudoColor || color_class == DirectColor) {
1233                cmap[0] = XCreateColormap(x_display, rootwin, vis, AllocAll);
1234                cmap[1] = XCreateColormap(x_display, rootwin, vis, AllocAll);
1235        }
1236
1237        // Find pixel format of direct modes
1238        if (color_class == DirectColor || color_class == TrueColor) {
1239                rshift = gshift = bshift = 0;
1240                rloss = gloss = bloss = 8;
1241                uint32 mask;
1242                for (mask=vis->red_mask; !(mask&1); mask>>=1)
1243                        ++rshift;
1244                for (; mask&1; mask>>=1)
1245                        --rloss;
1246                for (mask=vis->green_mask; !(mask&1); mask>>=1)
1247                        ++gshift;
1248                for (; mask&1; mask>>=1)
1249                        --gloss;
1250                for (mask=vis->blue_mask; !(mask&1); mask>>=1)
1251                        ++bshift;
1252                for (; mask&1; mask>>=1)
1253                        --bloss;
1254        }
1255
1256        // Preset palette pixel values for gamma table
1257        if (color_class == DirectColor) {
1258                int num = vis->map_entries;
1259                for (int i=0; i<num; i++) {
1260                        int c = (i * 256) / num;
1261                        palette[i].pixel = map_rgb(c, c, c);
1262                }
1263        }
1264
1445          // Get screen mode from preferences
1446          const char *mode_str;
1447          if (classic_mode)
# Line 1296 | Line 1476 | bool VideoInit(bool classic)
1476                  default_height = DisplayHeight(x_display, screen);
1477  
1478          // Mac screen depth follows X depth
1479 <        video_depth default_depth = DepthModeForPixelDepth(xdepth);
1479 >        video_depth default_depth = VDEPTH_1BIT;
1480 >        switch (DefaultDepth(x_display, screen)) {
1481 >                case 8:
1482 >                        default_depth = VDEPTH_8BIT;
1483 >                        break;
1484 >                case 15: case 16:
1485 >                        default_depth = VDEPTH_16BIT;
1486 >                        break;
1487 >                case 24: case 32:
1488 >                        default_depth = VDEPTH_32BIT;
1489 >                        break;
1490 >        }
1491  
1492          // Construct list of supported modes
1493          if (display_type == DISPLAY_WINDOW) {
1494                  if (classic)
1495                          add_mode(512, 342, 0x80, 64, VDEPTH_1BIT);
1496                  else {
1497 <                        if (default_depth != VDEPTH_1BIT)
1498 <                                add_window_modes(VDEPTH_1BIT);  // 1-bit modes are always available
1499 < #ifdef ENABLE_VOSF
1309 <                        if (default_depth > VDEPTH_8BIT) {
1310 <                                add_window_modes(VDEPTH_2BIT);  // 2, 4 and 8-bit modes are also possible on 16/32-bit screens with VOSF blitters
1311 <                                add_window_modes(VDEPTH_4BIT);
1312 <                                add_window_modes(VDEPTH_8BIT);
1497 >                        for (unsigned d=VDEPTH_1BIT; d<=VDEPTH_32BIT; d++) {
1498 >                                if (find_visual_for_depth(video_depth(d)))
1499 >                                        add_window_modes(video_depth(d));
1500                          }
1314 #endif
1315                        add_window_modes(default_depth);
1501                  }
1502          } else
1503                  add_mode(default_width, default_height, 0x80, TrivialBytesPerRow(default_width, default_depth), default_depth);
1504 +        if (VideoModes.empty()) {
1505 +                ErrorAlert(STR_NO_XVISUAL_ERR);
1506 +                return false;
1507 +        }
1508 +        video_init_depth_list();
1509 +
1510 + #if DEBUG
1511 +        D(bug("Available video modes:\n"));
1512 +        vector<video_mode>::const_iterator i = VideoModes.begin(), end = VideoModes.end();
1513 +        while (i != end) {
1514 +                int bits = 1 << i->depth;
1515 +                if (bits == 16)
1516 +                        bits = 15;
1517 +                else if (bits == 32)
1518 +                        bits = 24;
1519 +                D(bug(" %dx%d (ID %02x), %d colors\n", i->x, i->y, i->resolution_id, 1 << bits));
1520 +                ++i;
1521 +        }
1522 + #endif
1523  
1524          // Find requested default mode and open display
1525          if (VideoModes.size() == 1)
# Line 1372 | Line 1576 | static void video_close(void)
1576          // Close display
1577          delete drv;
1578          drv = NULL;
1375 }
1376
1377 void VideoExit(void)
1378 {
1379        // Close display
1380        video_close();
1579  
1580          // Free colormaps
1581          if (cmap[0]) {
# Line 1388 | Line 1586 | void VideoExit(void)
1586                  XFreeColormap(x_display, cmap[1]);
1587                  cmap[1] = 0;
1588          }
1589 + }
1590 +
1591 + void VideoExit(void)
1592 + {
1593 +        // Close display
1594 +        video_close();
1595  
1596   #ifdef ENABLE_XF86_VIDMODE
1597          // Free video mode list
# Line 1404 | Line 1608 | void VideoExit(void)
1608                  fbdev_fd = -1;
1609          }
1610   #endif
1611 +
1612 +        // Free depth list
1613 +        if (avail_depths) {
1614 +                XFree(avail_depths);
1615 +                avail_depths = NULL;
1616 +        }
1617   }
1618  
1619  
# Line 1455 | Line 1665 | void video_set_palette(uint8 *pal, int n
1665                  p->red = pal[c*3 + 0] * 0x0101;
1666                  p->green = pal[c*3 + 1] * 0x0101;
1667                  p->blue = pal[c*3 + 2] * 0x0101;
1668 <                if (vis->c_class == PseudoColor)
1668 >                if (color_class == PseudoColor)
1669                          p->pixel = i;
1670                  p->flags = DoRed | DoGreen | DoBlue;
1671                  p++;
# Line 1463 | Line 1673 | void video_set_palette(uint8 *pal, int n
1673  
1674   #ifdef ENABLE_VOSF
1675          // Recalculate pixel color expansion map
1676 <        if (!IsDirectMode(VideoMonitor.mode) && (vis->c_class == TrueColor || vis->c_class == DirectColor)) {
1676 >        if (!IsDirectMode(VideoMonitor.mode) && (color_class == TrueColor || color_class == DirectColor)) {
1677                  for (int i=0; i<256; i++) {
1678 <                        int c = i % num_in; // If there are less than 256 colors, we repeat the first entries (this makes color expansion easier)
1678 >                        int c = i & (num_in-1); // If there are less than 256 colors, we repeat the first entries (this makes color expansion easier)
1679                          ExpandMap[i] = map_rgb(pal[c*3+0], pal[c*3+1], pal[c*3+2]);
1680                  }
1681  
# Line 1502 | Line 1712 | void video_switch_to_mode(const video_mo
1712  
1713  
1714   /*
1715 < *  Translate key event to Mac keycode
1715 > *  Translate key event to Mac keycode, returns -1 if no keycode was found
1716 > *  and -2 if the key was recognized as a hotkey
1717   */
1718  
1719 < static int kc_decode(KeySym ks)
1719 > static int kc_decode(KeySym ks, bool key_down)
1720   {
1721          switch (ks) {
1722                  case XK_A: case XK_a: return 0x00;
# Line 1558 | Line 1769 | static int kc_decode(KeySym ks)
1769                  case XK_period: case XK_greater: return 0x2f;
1770                  case XK_slash: case XK_question: return 0x2c;
1771  
1772 < #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
1772 >                case XK_Tab: if (ctrl_down) {if (key_down) drv->suspend(); return -2;} else return 0x30;
1773                  case XK_Return: return 0x24;
1774                  case XK_space: return 0x31;
1775                  case XK_BackSpace: return 0x33;
# Line 1596 | Line 1803 | static int kc_decode(KeySym ks)
1803                  case XK_Left: return 0x3b;
1804                  case XK_Right: return 0x3c;
1805  
1806 <                case XK_Escape: if (ctrl_down) {quit_full_screen = true; emerg_quit = true; return -1;} else return 0x35;
1806 >                case XK_Escape: if (ctrl_down) {if (key_down) { quit_full_screen = true; emerg_quit = true; } return -2;} else return 0x35;
1807  
1808 <                case XK_F1: if (ctrl_down) {SysMountFirstFloppy(); return -1;} else return 0x7a;
1808 >                case XK_F1: if (ctrl_down) {if (key_down) SysMountFirstFloppy(); return -2;} else return 0x7a;
1809                  case XK_F2: return 0x78;
1810                  case XK_F3: return 0x63;
1811                  case XK_F4: return 0x76;
1812 <                case XK_F5: return 0x60;
1812 >                case XK_F5: if (ctrl_down) {if (key_down) drv->toggle_mouse_grab(); return -2;} else return 0x60;
1813                  case XK_F6: return 0x61;
1814                  case XK_F7: return 0x62;
1815                  case XK_F8: return 0x64;
# Line 1650 | Line 1857 | static int kc_decode(KeySym ks)
1857          return -1;
1858   }
1859  
1860 < static int event2keycode(XKeyEvent &ev)
1860 > static int event2keycode(XKeyEvent &ev, bool key_down)
1861   {
1862          KeySym ks;
1656        int as;
1863          int i = 0;
1864  
1865          do {
1866                  ks = XLookupKeysym(&ev, i++);
1867 <                as = kc_decode(ks);
1868 <                if (as != -1)
1867 >                int as = kc_decode(ks, key_down);
1868 >                if (as >= 0)
1869 >                        return as;
1870 >                if (as == -2)
1871                          return as;
1872          } while (ks != NoSymbol);
1873  
# Line 1706 | Line 1914 | static void handle_events(void)
1914                          }
1915  
1916                          // Mouse moved
1709                        case EnterNotify:
1917                          case MotionNotify:
1918 <                                ADBMouseMoved(event.xmotion.x, event.xmotion.y);
1918 >                                drv->mouse_moved(event.xmotion.x, event.xmotion.y);
1919                                  break;
1920  
1921                          // Keyboard
1922                          case KeyPress: {
1923 <                                int code;
1923 >                                int code = -1;
1924                                  if (use_keycodes) {
1925 <                                        event2keycode(event.xkey);      // This is called to process the hotkeys
1926 <                                        code = keycode_table[event.xkey.keycode & 0xff];
1925 >                                        if (event2keycode(event.xkey, true) != -2)      // This is called to process the hotkeys
1926 >                                                code = keycode_table[event.xkey.keycode & 0xff];
1927                                  } else
1928 <                                        code = event2keycode(event.xkey);
1929 <                                if (code != -1) {
1928 >                                        code = event2keycode(event.xkey, true);
1929 >                                if (code >= 0) {
1930                                          if (!emul_suspended) {
1931                                                  if (code == 0x39) {     // Caps Lock pressed
1932                                                          if (caps_on) {
# Line 1741 | Line 1948 | static void handle_events(void)
1948                                  break;
1949                          }
1950                          case KeyRelease: {
1951 <                                int code;
1951 >                                int code = -1;
1952                                  if (use_keycodes) {
1953 <                                        event2keycode(event.xkey);      // This is called to process the hotkeys
1954 <                                        code = keycode_table[event.xkey.keycode & 0xff];
1953 >                                        if (event2keycode(event.xkey, false) != -2)     // This is called to process the hotkeys
1954 >                                                code = keycode_table[event.xkey.keycode & 0xff];
1955                                  } else
1956 <                                        code = event2keycode(event.xkey);
1957 <                                if (code != -1 && code != 0x39) {       // Don't propagate Caps Lock releases
1956 >                                        code = event2keycode(event.xkey, false);
1957 >                                if (code >= 0 && code != 0x39) {        // Don't propagate Caps Lock releases
1958                                          ADBKeyUp(code);
1959                                          if (code == 0x36)
1960                                                  ctrl_down = false;
# Line 2011 | Line 2218 | static void update_display_static(driver
2218  
2219   static inline void possibly_quit_dga_mode()
2220   {
2221 <        // Quit DGA mode if requested
2221 >        // Quit DGA mode if requested (something terrible has happened and we
2222 >        // want to give control back to the user)
2223          if (quit_full_screen) {
2224                  quit_full_screen = false;
2225                  delete drv;
# Line 2019 | Line 2227 | static inline void possibly_quit_dga_mod
2227          }
2228   }
2229  
2230 + static inline void possibly_ungrab_mouse()
2231 + {
2232 +        // Ungrab mouse if requested (something terrible has happened and we
2233 +        // want to give control back to the user)
2234 +        if (quit_full_screen) {
2235 +                quit_full_screen = false;
2236 +                if (drv)
2237 +                        drv->ungrab_mouse();
2238 +        }
2239 + }
2240 +
2241   static inline void handle_palette_changes(void)
2242   {
2243          LOCK_PALETTE;
# Line 2071 | Line 2290 | static void video_refresh_dga_vosf(void)
2290  
2291   static void video_refresh_window_vosf(void)
2292   {
2293 <        // Quit DGA mode if requested
2294 <        possibly_quit_dga_mode();
2293 >        // Ungrab mouse if requested
2294 >        possibly_ungrab_mouse();
2295          
2296          // Handle X events
2297          handle_events();
# Line 2096 | Line 2315 | static void video_refresh_window_vosf(vo
2315  
2316   static void video_refresh_window_static(void)
2317   {
2318 +        // Ungrab mouse if requested
2319 +        possibly_ungrab_mouse();
2320 +
2321          // Handle X events
2322          handle_events();
2323          
# Line 2112 | Line 2334 | static void video_refresh_window_static(
2334  
2335   static void video_refresh_window_dynamic(void)
2336   {
2337 +        // Ungrab mouse if requested
2338 +        possibly_ungrab_mouse();
2339 +
2340          // Handle X events
2341          handle_events();
2342          

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines