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

Comparing SheepShaver/src/Unix/video_x.cpp (file contents):
Revision 1.6 by gbeauche, 2003-11-21T17:01:33Z vs.
Revision 1.12 by gbeauche, 2004-01-14T23:15:41Z

# Line 1 | Line 1
1   /*
2   *  video_x.cpp - Video/graphics emulation, X11 specific stuff
3   *
4 < *  SheepShaver (C) 1997-2002 Marc Hellwig and Christian Bauer
4 > *  SheepShaver (C) 1997-2004 Marc Hellwig and Christian Bauer
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
# Line 27 | Line 27
27   #include <sys/ipc.h>
28   #include <sys/shm.h>
29   #include <errno.h>
30 <
31 < #ifdef HAVE_PTHREADS
32 < # include <pthread.h>
33 < #endif
30 > #include <pthread.h>
31  
32   #ifdef ENABLE_XF86_DGA
33   #include <X11/extensions/xf86dga.h>
# Line 57 | Line 54 | const char KEYCODE_FILE_NAME[] = DATADIR
54  
55   // Global variables
56   static int32 frame_skip;
57 + static int16 mouse_wheel_mode;
58 + static int16 mouse_wheel_lines;
59   static bool redraw_thread_active = false;       // Flag: Redraw thread installed
60   static pthread_t redraw_thread;                         // Redraw thread
61  
# Line 136 | Line 135 | extern Display *x_display;
135   // From sys_unix.cpp
136   extern void SysMountFirstFloppy(void);
137  
138 + // From clip_unix.cpp
139 + extern void ClipboardSelectionClear(XSelectionClearEvent *);
140 + extern void ClipboardSelectionRequest(XSelectionRequestEvent *);
141 +
142  
143   // Video acceleration through SIGSEGV
144   #ifdef ENABLE_VOSF
# Line 169 | Line 172 | static bool open_window(int width, int h
172          // Set absolute mouse mode
173          ADBSetRelMouseMode(false);
174  
172        // Read frame skip prefs
173        frame_skip = PrefsFindInt32("frameskip");
174        if (frame_skip == 0)
175                frame_skip = 1;
176
175          // Create window
176          XSetWindowAttributes wattr;
177          wattr.event_mask = eventmask = win_eventmask;
# Line 685 | Line 683 | bool VideoInit(void)
683          // Init keycode translation
684          keycode_init();
685  
686 +        // Read frame skip prefs
687 +        frame_skip = PrefsFindInt32("frameskip");
688 +        if (frame_skip == 0)
689 +                frame_skip = 1;
690 +
691 +        // Read mouse wheel prefs
692 +        mouse_wheel_mode = PrefsFindInt32("mousewheelmode");
693 +        mouse_wheel_lines = PrefsFindInt32("mousewheellines");
694 +
695          // Init variables
696          private_data = NULL;
697          cur_mode = 0;   // Window 640x480
# Line 961 | Line 968 | static void resume_emul(void)
968          // Reopen full screen display
969          XGrabKeyboard(x_display, rootwin, 1, GrabModeAsync, GrabModeAsync, CurrentTime);
970          XGrabPointer(x_display, rootwin, 1, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
971 + #ifdef ENABLE_XF86_DGA
972          XF86DGADirectVideo(x_display, screen, XF86DGADirectGraphics | XF86DGADirectKeyb | XF86DGADirectMouse);
973          XF86DGASetViewPort(x_display, screen, 0, 0);
974 + #endif
975          XSync(x_display, false);
976  
977          // the_buffer already contains the data to restore. i.e. since a temporary
# Line 1178 | Line 1187 | static void handle_events(void)
1187          for (;;) {
1188                  XEvent event;
1189  
1190 <                if (!XCheckMaskEvent(x_display, eventmask, &event))
1190 >                XDisplayLock();
1191 >                if (!XCheckMaskEvent(x_display, eventmask, &event)) {
1192 >                        // Handle clipboard events
1193 >                        if (XCheckTypedEvent(x_display, SelectionRequest, &event))
1194 >                                ClipboardSelectionRequest(&event.xselectionrequest);
1195 >                        else if (XCheckTypedEvent(x_display, SelectionClear, &event))
1196 >                                ClipboardSelectionClear(&event.xselectionclear);
1197 >
1198 >                        XDisplayUnlock();
1199                          break;
1200 +                }
1201 +                XDisplayUnlock();
1202  
1203                  switch (event.type) {
1204                          // Mouse button
# Line 1187 | Line 1206 | static void handle_events(void)
1206                                  unsigned int button = ((XButtonEvent *)&event)->button;
1207                                  if (button < 4)
1208                                          ADBMouseDown(button - 1);
1209 +                                else if (button < 6) {  // Wheel mouse
1210 +                                        if (mouse_wheel_mode == 0) {
1211 +                                                int key = (button == 5) ? 0x79 : 0x74;  // Page up/down
1212 +                                                ADBKeyDown(key);
1213 +                                                ADBKeyUp(key);
1214 +                                        } else {
1215 +                                                int key = (button == 5) ? 0x3d : 0x3e;  // Cursor up/down
1216 +                                                for(int i=0; i<mouse_wheel_lines; i++) {
1217 +                                                        ADBKeyDown(key);
1218 +                                                        ADBKeyUp(key);
1219 +                                                }
1220 +                                        }
1221 +                                }
1222                                  break;
1223                          }
1224                          case ButtonRelease: {
# Line 1593 | Line 1625 | static void update_display(void)
1625  
1626          // Refresh display
1627          if (high && wide) {
1628 +                XDisplayLock();
1629                  if (have_shm)
1630                          XShmPutImage(x_display, the_win, the_gc, img, x1, y1, x1, y1, wide, high, 0);
1631                  else
1632                          XPutImage(x_display, the_win, the_gc, img, x1, y1, x1, y1, wide, high);
1633 +                XDisplayUnlock();
1634          }
1635   }
1636  
1637 + const int VIDEO_REFRESH_HZ = 60;
1638 + const int VIDEO_REFRESH_DELAY = 1000000 / VIDEO_REFRESH_HZ;
1639 +
1640   static void *redraw_func(void *arg)
1641   {
1642 <        int tick_counter = 0;
1606 <        struct timespec req = {0, 16666667};
1642 >        int fd = ConnectionNumber(x_display);
1643  
1644 <        for (;;) {
1644 >        uint64 start = GetTicks_usec();
1645 >        int64 ticks = 0;
1646 >        uint64 next = GetTicks_usec() + VIDEO_REFRESH_DELAY;
1647  
1648 <                // Wait
1611 <                nanosleep(&req, NULL);
1648 >        for (;;) {
1649  
1650                  // Pause if requested (during video mode switches)
1651                  while (thread_stop_req)
1652                          thread_stop_ack = true;
1653  
1654 <                // Handle X11 events
1655 <                handle_events();
1654 >                int64 delay = next - GetTicks_usec();
1655 >                if (delay < -VIDEO_REFRESH_DELAY) {
1656 >
1657 >                        // We are lagging far behind, so we reset the delay mechanism
1658 >                        next = GetTicks_usec();
1659 >
1660 >                } else if (delay <= 0) {
1661 >
1662 >                        // Delay expired, refresh display
1663 >                        next += VIDEO_REFRESH_DELAY;
1664 >                        ticks++;
1665 >
1666 >                        // Handle X11 events
1667 >                        handle_events();
1668  
1669 <                // Quit DGA mode if requested
1670 <                if (quit_full_screen) {
1671 <                        quit_full_screen = false;
1672 <                        if (display_type == DIS_SCREEN) {
1669 >                        // Quit DGA mode if requested
1670 >                        if (quit_full_screen) {
1671 >                                quit_full_screen = false;
1672 >                                if (display_type == DIS_SCREEN) {
1673 >                                        XDisplayLock();
1674   #ifdef ENABLE_XF86_DGA
1675 <                                XF86DGADirectVideo(x_display, screen, 0);
1676 <                                XUngrabPointer(x_display, CurrentTime);
1677 <                                XUngrabKeyboard(x_display, CurrentTime);
1678 < #endif
1679 <                                XSync(x_display, false);
1680 <                                quit_full_screen_ack = true;
1681 <                                return NULL;
1675 >                                        XF86DGADirectVideo(x_display, screen, 0);
1676 >                                        XUngrabPointer(x_display, CurrentTime);
1677 >                                        XUngrabKeyboard(x_display, CurrentTime);
1678 > #endif
1679 >                                        XSync(x_display, false);
1680 >                                        XDisplayUnlock();
1681 >                                        quit_full_screen_ack = true;
1682 >                                        return NULL;
1683 >                                }
1684                          }
1633                }
1685  
1686 <                // Refresh display and set cursor image in window mode
1687 <                if (display_type == DIS_WINDOW) {
1688 <                        tick_counter++;
1689 <                        if (tick_counter >= frame_skip) {
1690 <                                tick_counter = 0;
1686 >                        // Refresh display and set cursor image in window mode
1687 >                        static int tick_counter = 0;
1688 >                        if (display_type == DIS_WINDOW) {
1689 >                                tick_counter++;
1690 >                                if (tick_counter >= frame_skip) {
1691 >                                        tick_counter = 0;
1692  
1693 <                                // Update display
1693 >                                        // Update display
1694   #ifdef ENABLE_VOSF
1695 <                                if (use_vosf) {
1696 <                                        if (mainBuffer.dirty) {
1697 <                                                LOCK_VOSF;
1698 <                                                update_display_window_vosf();
1699 <                                                UNLOCK_VOSF;
1700 <                                                XSync(x_display, false); // Let the server catch up
1695 >                                        if (use_vosf) {
1696 >                                                XDisplayLock();
1697 >                                                if (mainBuffer.dirty) {
1698 >                                                        LOCK_VOSF;
1699 >                                                        update_display_window_vosf();
1700 >                                                        UNLOCK_VOSF;
1701 >                                                        XSync(x_display, false); // Let the server catch up
1702 >                                                }
1703 >                                                XDisplayUnlock();
1704                                          }
1705 <                                }
1651 <                                else
1705 >                                        else
1706   #endif
1707 <                                        update_display();
1707 >                                                update_display();
1708  
1709 <                                // Set new cursor image if it was changed
1710 <                                if (cursor_changed) {
1711 <                                        cursor_changed = false;
1712 <                                        memcpy(cursor_image->data, MacCursor + 4, 32);
1713 <                                        memcpy(cursor_mask_image->data, MacCursor + 36, 32);
1714 <                                        XFreeCursor(x_display, mac_cursor);
1715 <                                        XPutImage(x_display, cursor_map, cursor_gc, cursor_image, 0, 0, 0, 0, 16, 16);
1716 <                                        XPutImage(x_display, cursor_mask_map, cursor_mask_gc, cursor_mask_image, 0, 0, 0, 0, 16, 16);
1717 <                                        mac_cursor = XCreatePixmapCursor(x_display, cursor_map, cursor_mask_map, &black, &white, MacCursor[2], MacCursor[3]);
1718 <                                        XDefineCursor(x_display, the_win, mac_cursor);
1709 >                                        // Set new cursor image if it was changed
1710 >                                        if (cursor_changed) {
1711 >                                                cursor_changed = false;
1712 >                                                memcpy(cursor_image->data, MacCursor + 4, 32);
1713 >                                                memcpy(cursor_mask_image->data, MacCursor + 36, 32);
1714 >                                                XDisplayLock();
1715 >                                                XFreeCursor(x_display, mac_cursor);
1716 >                                                XPutImage(x_display, cursor_map, cursor_gc, cursor_image, 0, 0, 0, 0, 16, 16);
1717 >                                                XPutImage(x_display, cursor_mask_map, cursor_mask_gc, cursor_mask_image, 0, 0, 0, 0, 16, 16);
1718 >                                                mac_cursor = XCreatePixmapCursor(x_display, cursor_map, cursor_mask_map, &black, &white, MacCursor[2], MacCursor[3]);
1719 >                                                XDefineCursor(x_display, the_win, mac_cursor);
1720 >                                                XDisplayUnlock();
1721 >                                        }
1722                                  }
1723                          }
1667                }
1724   #ifdef ENABLE_VOSF
1725 <                else if (use_vosf) {
1726 <                        // Update display (VOSF variant)
1727 <                        static int tick_counter = 0;
1728 <                        if (++tick_counter >= frame_skip) {
1729 <                                tick_counter = 0;
1730 <                                if (mainBuffer.dirty) {
1731 <                                        LOCK_VOSF;
1732 <                                        update_display_dga_vosf();
1733 <                                        UNLOCK_VOSF;
1725 >                        else if (use_vosf) {
1726 >                                // Update display (VOSF variant)
1727 >                                if (++tick_counter >= frame_skip) {
1728 >                                        tick_counter = 0;
1729 >                                        if (mainBuffer.dirty) {
1730 >                                                LOCK_VOSF;
1731 >                                                update_display_dga_vosf();
1732 >                                                UNLOCK_VOSF;
1733 >                                        }
1734                                  }
1735                          }
1680                }
1736   #endif
1737  
1738 <                // Set new palette if it was changed
1739 <                if (palette_changed && !emul_suspended) {
1740 <                        palette_changed = false;
1741 <                        XColor c[256];
1742 <                        for (int i=0; i<256; i++) {
1743 <                                c[i].pixel = i;
1744 <                                c[i].red = mac_pal[i].red * 0x0101;
1745 <                                c[i].green = mac_pal[i].green * 0x0101;
1746 <                                c[i].blue = mac_pal[i].blue * 0x0101;
1747 <                                c[i].flags = DoRed | DoGreen | DoBlue;
1693 <                        }
1694 <                        if (depth == 8) {
1695 <                                XStoreColors(x_display, cmap[0], c, 256);
1696 <                                XStoreColors(x_display, cmap[1], c, 256);
1697 < #ifdef ENABLE_XF86_DGA
1698 <                                if (display_type == DIS_SCREEN) {
1699 <                                        current_dga_cmap ^= 1;
1700 <                                        XF86DGAInstallColormap(x_display, screen, cmap[current_dga_cmap]);
1738 >                        // Set new palette if it was changed
1739 >                        if (palette_changed && !emul_suspended) {
1740 >                                palette_changed = false;
1741 >                                XColor c[256];
1742 >                                for (int i=0; i<256; i++) {
1743 >                                        c[i].pixel = i;
1744 >                                        c[i].red = mac_pal[i].red * 0x0101;
1745 >                                        c[i].green = mac_pal[i].green * 0x0101;
1746 >                                        c[i].blue = mac_pal[i].blue * 0x0101;
1747 >                                        c[i].flags = DoRed | DoGreen | DoBlue;
1748                                  }
1749 +                                if (depth == 8) {
1750 +                                        XDisplayLock();
1751 +                                        XStoreColors(x_display, cmap[0], c, 256);
1752 +                                        XStoreColors(x_display, cmap[1], c, 256);
1753 + #ifdef ENABLE_XF86_DGA
1754 +                                        if (display_type == DIS_SCREEN) {
1755 +                                                current_dga_cmap ^= 1;
1756 +                                                XF86DGAInstallColormap(x_display, screen, cmap[current_dga_cmap]);
1757 +                                        }
1758   #endif
1759 +                                        XDisplayUnlock();
1760 +                                }
1761                          }
1762 +
1763 +                } else {
1764 +
1765 +                        // No display refresh pending, check for X events
1766 +                        fd_set readfds;
1767 +                        FD_ZERO(&readfds);
1768 +                        FD_SET(fd, &readfds);
1769 +                        struct timeval timeout;
1770 +                        timeout.tv_sec = 0;
1771 +                        timeout.tv_usec = delay;
1772 +                        if (select(fd+1, &readfds, NULL, NULL, &timeout) > 0)
1773 +                                handle_events();
1774                  }
1775          }
1776          return NULL;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines