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.3 by gbeauche, 2003-05-22T22:12:05Z vs.
Revision 1.9 by gbeauche, 2003-12-31T11:37:26Z

# 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-2003 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 18 | Line 18
18   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19   */
20  
21 + #include "sysdeps.h"
22 +
23   #include <X11/Xlib.h>
24   #include <X11/Xutil.h>
25   #include <X11/keysym.h>
26   #include <X11/extensions/XShm.h>
27   #include <sys/ipc.h>
28   #include <sys/shm.h>
29 + #include <errno.h>
30   #include <pthread.h>
31  
32 < #include "sysdeps.h"
32 > #ifdef ENABLE_XF86_DGA
33 > #include <X11/extensions/xf86dga.h>
34 > #endif
35 >
36 > #ifdef ENABLE_XF86_VIDMODE
37 > # include <X11/extensions/xf86vmode.h>
38 > #endif
39 >
40   #include "main.h"
41   #include "adb.h"
42   #include "prefs.h"
# Line 38 | Line 48
48   #define DEBUG 0
49   #include "debug.h"
50  
41 #ifdef ENABLE_XF86_DGA
42 #include <X11/extensions/xf86dga.h>
43 #endif
44
45 #ifdef ENABLE_XF86_VIDMODE
46 #include <X11/extensions/xf86vmode.h>
47 #endif
51  
52 + // Constants
53 + const char KEYCODE_FILE_NAME[] = DATADIR "/keycodes";
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  
62 + static bool local_X11;                                          // Flag: X server running on local machine?
63   static volatile bool thread_stop_req = false;
64   static volatile bool thread_stop_ack = false;   // Acknowledge for thread_stop_req
65  
# Line 73 | Line 81 | static bool emerg_quit = false;                                // Fl
81   static bool emul_suspended = false;                     // Flag: emulator suspended
82   static Window suspend_win;                                      // "Suspend" window
83   static void *fb_save = NULL;                            // Saved frame buffer for suspend
84 + static bool use_keycodes = false;                       // Flag: Use keycodes rather than keysyms
85 + static int keycode_table[256];                          // X keycode -> Mac keycode translation table
86  
87   // X11 variables
88   static int screen;                                                      // Screen number
# Line 118 | Line 128 | static int num_x_video_modes;
128   static void *redraw_func(void *arg);
129  
130  
131 < // From main_linux.cpp
131 > // From main_unix.cpp
132 > extern char *x_display_name;
133   extern Display *x_display;
134  
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 + extern void ClipboardSelectionNotify(XSelectionEvent *req);
142 +
143  
144   // Video acceleration through SIGSEGV
145   #ifdef ENABLE_VOSF
# Line 157 | Line 173 | static bool open_window(int width, int h
173          // Set absolute mouse mode
174          ADBSetRelMouseMode(false);
175  
160        // Read frame skip prefs
161        frame_skip = PrefsFindInt32("frameskip");
162        if (frame_skip == 0)
163                frame_skip = 1;
164
176          // Create window
177          XSetWindowAttributes wattr;
178          wattr.event_mask = eventmask = win_eventmask;
# Line 195 | Line 206 | static bool open_window(int width, int h
206                  XFree((char *)hints);
207          }
208  
209 +        // 1-bit mode is big-endian; if the X server is little-endian, we can't
210 +        // use SHM because that doesn't allow changing the image byte order
211 +        bool need_msb_image = (depth == 1 && XImageByteOrder(x_display) == LSBFirst);
212 +
213          // Try to create and attach SHM image
214          have_shm = false;
215 <        if (depth != 1 && XShmQueryExtension(x_display)) {
215 >        if (local_X11 && !need_msb_image && XShmQueryExtension(x_display)) {
216  
217                  // Create SHM image ("height + 2" for safety)
218 <                img = XShmCreateImage(x_display, vis, depth, depth == 1 ? XYBitmap : ZPixmap, 0, &shminfo, width, height);
218 >                img = XShmCreateImage(x_display, vis, depth == 1 ? 1 : xdepth, depth == 1 ? XYBitmap : ZPixmap, 0, &shminfo, width, height);
219                  shminfo.shmid = shmget(IPC_PRIVATE, (height + 2) * img->bytes_per_line, IPC_CREAT | 0777);
220                  the_buffer_copy = (uint8 *)shmat(shminfo.shmid, 0, 0);
221                  shminfo.shmaddr = img->data = (char *)the_buffer_copy;
# Line 528 | Line 543 | static void close_display(void)
543   *  Initialization
544   */
545  
546 + // Init keycode translation table
547 + static void keycode_init(void)
548 + {
549 +        bool use_kc = PrefsFindBool("keycodes");
550 +        if (use_kc) {
551 +
552 +                // Get keycode file path from preferences
553 +                const char *kc_path = PrefsFindString("keycodefile");
554 +
555 +                // Open keycode table
556 +                FILE *f = fopen(kc_path ? kc_path : KEYCODE_FILE_NAME, "r");
557 +                if (f == NULL) {
558 +                        char str[256];
559 +                        sprintf(str, GetString(STR_KEYCODE_FILE_WARN), kc_path ? kc_path : KEYCODE_FILE_NAME, strerror(errno));
560 +                        WarningAlert(str);
561 +                        return;
562 +                }
563 +
564 +                // Default translation table
565 +                for (int i=0; i<256; i++)
566 +                        keycode_table[i] = -1;
567 +
568 +                // Search for server vendor string, then read keycodes
569 +                const char *vendor = ServerVendor(x_display);
570 +                bool vendor_found = false;
571 +                char line[256];
572 +                while (fgets(line, 255, f)) {
573 +                        // Read line
574 +                        int len = strlen(line);
575 +                        if (len == 0)
576 +                                continue;
577 +                        line[len-1] = 0;
578 +
579 +                        // Comments begin with "#" or ";"
580 +                        if (line[0] == '#' || line[0] == ';' || line[0] == 0)
581 +                                continue;
582 +
583 +                        if (vendor_found) {
584 +                                // Read keycode
585 +                                int x_code, mac_code;
586 +                                if (sscanf(line, "%d %d", &x_code, &mac_code) == 2)
587 +                                        keycode_table[x_code & 0xff] = mac_code;
588 +                                else
589 +                                        break;
590 +                        } else {
591 +                                // Search for vendor string
592 +                                if (strstr(vendor, line) == vendor)
593 +                                        vendor_found = true;
594 +                        }
595 +                }
596 +
597 +                // Keycode file completely read
598 +                fclose(f);
599 +                use_keycodes = vendor_found;
600 +
601 +                // Vendor not found? Then display warning
602 +                if (!vendor_found) {
603 +                        char str[256];
604 +                        sprintf(str, GetString(STR_KEYCODE_VENDOR_WARN), vendor, kc_path ? kc_path : KEYCODE_FILE_NAME);
605 +                        WarningAlert(str);
606 +                        return;
607 +                }
608 +        }
609 + }
610 +
611   static void add_mode(VideoInfo *&p, uint32 allow, uint32 test, long apple_mode, long apple_id, int type)
612   {
613          if (allow & test) {
# Line 597 | Line 677 | bool VideoInit(void)
677          mainBuffer.pageInfo = NULL;
678   #endif
679          
680 +        // Check if X server runs on local machine
681 +        local_X11 = (strncmp(XDisplayName(x_display_name), ":", 1) == 0)
682 +                 || (strncmp(XDisplayName(x_display_name), "unix:", 5) == 0);
683 +    
684 +        // Init keycode translation
685 +        keycode_init();
686 +
687 +        // Read frame skip prefs
688 +        frame_skip = PrefsFindInt32("frameskip");
689 +        if (frame_skip == 0)
690 +                frame_skip = 1;
691 +
692 +        // Read mouse wheel prefs
693 +        mouse_wheel_mode = PrefsFindInt32("mousewheelmode");
694 +        mouse_wheel_lines = PrefsFindInt32("mousewheellines");
695 +
696          // Init variables
697          private_data = NULL;
698          cur_mode = 0;   // Window 640x480
# Line 612 | Line 708 | bool VideoInit(void)
708   #ifdef ENABLE_XF86_DGA
709          // DGA available?
710      int event_base, error_base;
711 <    if (XF86DGAQueryExtension(x_display, &event_base, &error_base)) {
711 >    if (local_X11 && XF86DGAQueryExtension(x_display, &event_base, &error_base)) {
712                  int dga_flags = 0;
713                  XF86DGAQueryDirectVideo(x_display, screen, &dga_flags);
714                  has_dga = dga_flags & XF86DGADirectPresent;
# Line 1068 | Line 1164 | static int kc_decode(KeySym ks)
1164          return -1;
1165   }
1166  
1167 < static int event2keycode(XKeyEvent *ev)
1167 > static int event2keycode(XKeyEvent &ev)
1168   {
1169          KeySym ks;
1170          int as;
1171          int i = 0;
1172  
1173          do {
1174 <                ks = XLookupKeysym(ev, i++);
1174 >                ks = XLookupKeysym(&ev, i++);
1175                  as = kc_decode(ks);
1176                  if (as != -1)
1177                          return as;
# Line 1090 | Line 1186 | static void handle_events(void)
1186          for (;;) {
1187                  XEvent event;
1188  
1189 <                if (!XCheckMaskEvent(x_display, eventmask, &event))
1189 >                if (!XCheckMaskEvent(x_display, eventmask, &event)) {
1190 >                        // Handle clipboard events
1191 >                        if (XCheckTypedEvent(x_display, SelectionRequest, &event))
1192 >                                ClipboardSelectionRequest(&event.xselectionrequest);
1193 >                        else if (XCheckTypedEvent(x_display, SelectionClear, &event))
1194 >                                ClipboardSelectionClear(&event.xselectionclear);
1195 >                        else if (XCheckTypedEvent(x_display, SelectionNotify, &event))
1196 >                                ClipboardSelectionNotify(&event.xselection);
1197                          break;
1198 +                }
1199  
1200                  switch (event.type) {
1201                          // Mouse button
# Line 1099 | Line 1203 | static void handle_events(void)
1203                                  unsigned int button = ((XButtonEvent *)&event)->button;
1204                                  if (button < 4)
1205                                          ADBMouseDown(button - 1);
1206 +                                else if (button < 6) {  // Wheel mouse
1207 +                                        if (mouse_wheel_mode == 0) {
1208 +                                                int key = (button == 5) ? 0x79 : 0x74;  // Page up/down
1209 +                                                ADBKeyDown(key);
1210 +                                                ADBKeyUp(key);
1211 +                                        } else {
1212 +                                                int key = (button == 5) ? 0x3d : 0x3e;  // Cursor up/down
1213 +                                                for(int i=0; i<mouse_wheel_lines; i++) {
1214 +                                                        ADBKeyDown(key);
1215 +                                                        ADBKeyUp(key);
1216 +                                                }
1217 +                                        }
1218 +                                }
1219                                  break;
1220                          }
1221                          case ButtonRelease: {
# Line 1118 | Line 1235 | static void handle_events(void)
1235  
1236                          // Keyboard
1237                          case KeyPress: {
1238 <                                int code;
1239 <                                if ((code = event2keycode((XKeyEvent *)&event)) != -1) {
1238 >                                int code = event2keycode(event.xkey);
1239 >                                if (use_keycodes && code != -1)
1240 >                                        code = keycode_table[event.xkey.keycode & 0xff];
1241 >                                if (code != -1) {
1242                                          if (!emul_suspended) {
1243                                                  ADBKeyDown(code);
1244                                                  if (code == 0x36)
# Line 1132 | Line 1251 | static void handle_events(void)
1251                                  break;
1252                          }
1253                          case KeyRelease: {
1254 <                                int code;
1255 <                                if ((code = event2keycode((XKeyEvent *)&event)) != -1) {
1254 >                                int code = event2keycode(event.xkey);
1255 >                                if (use_keycodes && code != 1)
1256 >                                        code = keycode_table[event.xkey.keycode & 0xff];
1257 >                                if (code != -1) {
1258                                          ADBKeyUp(code);
1259                                          if (code == 0x36)
1260                                                  ctrl_down = false;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines