2 #include "bcresources.h"
3 #include "bcwindowbase.h"
4 #include "colormodels.h"
11 #define _(String) gettext(String)
12 #define gettext_noop(String) String
13 #define N_(String) gettext_noop (String)
20 // 24 bpp unpacked: 0bgr
23 BC_Capture::BC_Capture(int w, int h, char *display_path)
30 init_window(display_path);
35 BC_Capture::~BC_Capture()
38 XCloseDisplay(display);
41 int BC_Capture::init_window(char *display_path)
44 if(display_path && display_path[0] == 0) display_path = NULL;
45 if((display = XOpenDisplay(display_path)) == NULL)
47 printf(_("cannot connect to X server.\n"));
48 if(getenv("DISPLAY") == NULL)
49 printf(_("'DISPLAY' environment variable not set.\n"));
54 screen = DefaultScreen(display);
55 rootwin = RootWindow(display, screen);
56 vis = DefaultVisual(display, screen);
57 default_depth = DefaultDepth(display, screen);
58 client_byte_order = (*(u_int32_t*)"a ") & 0x00000001;
59 server_byte_order = (XImageByteOrder(display) == MSBFirst) ? 0 : 1;
62 ximage = XCreateImage(display,
72 bits_per_pixel = ximage->bits_per_pixel;
73 XDestroyImage(ximage);
74 bitmap_color_model = BC_WindowBase::evaluate_color_model(client_byte_order, server_byte_order, bits_per_pixel);
77 // This doesn't ensure the X Server is on the local host
78 if(use_shm && !XShmQueryExtension(display))
86 int BC_Capture::allocate_data()
89 if(!display) return 1;
92 ximage = XShmCreateImage(display, vis, default_depth, ZPixmap, (char*)NULL, &shm_info, w, h);
94 shm_info.shmid = shmget(IPC_PRIVATE, h * ximage->bytes_per_line, IPC_CREAT | 0777);
95 if(shm_info.shmid < 0) perror("BC_Capture::allocate_data shmget");
96 data = (unsigned char *)shmat(shm_info.shmid, NULL, 0);
97 shmctl(shm_info.shmid, IPC_RMID, 0);
98 ximage->data = shm_info.shmaddr = (char*)data; // setting ximage->data stops BadValue
99 shm_info.readOnly = 0;
101 // Crashes here if remote server.
102 BC_Resources::error = 0;
103 XShmAttach(display, &shm_info);
104 XSync(display, False);
105 if(BC_Resources::error)
107 XDestroyImage(ximage);
108 shmdt(shm_info.shmaddr);
115 // need to use bytes_per_line for some X servers
117 ximage = XCreateImage(display, vis, default_depth, ZPixmap, 0, (char*)data, w, h, 8, 0);
118 data = (unsigned char*)malloc(h * ximage->bytes_per_line);
119 XDestroyImage(ximage);
121 ximage = XCreateImage(display, vis, default_depth, ZPixmap, 0, (char*)data, w, h, 8, 0);
124 row_data = new unsigned char*[h];
125 for(int i = 0; i < h; i++)
127 row_data[i] = &data[i * ximage->bytes_per_line];
129 // This differs from the depth parameter of the top_level.
130 bits_per_pixel = ximage->bits_per_pixel;
134 int BC_Capture::delete_data()
136 if(!display) return 1;
141 XShmDetach(display, &shm_info);
142 XDestroyImage(ximage);
143 shmdt(shm_info.shmaddr);
147 XDestroyImage(ximage);
150 // data is automatically freed by XDestroyImage
158 int BC_Capture::get_w() { return w; }
159 int BC_Capture::get_h() { return h; }
161 // Capture a frame from the screen
162 #define CAPTURE_FRAME_HEAD \
163 for(int i = 0; i < h; i++) \
165 unsigned char *input_row = row_data[i]; \
166 unsigned char *output_row = (unsigned char*)frame->get_rows()[i]; \
167 for(int j = 0; j < w; j++) \
170 #define CAPTURE_FRAME_TAIL \
176 int BC_Capture::capture_frame(VFrame *frame, int &x1, int &y1)
178 if(!display) return 1;
181 if(x1 > get_top_w() - w) x1 = get_top_w() - w;
182 if(y1 > get_top_h() - h) y1 = get_top_h() - h;
187 XShmGetImage(display, rootwin, ximage, x1, y1, 0xffffffff);
189 XGetSubImage(display, rootwin, x1, y1, w, h, 0xffffffff, ZPixmap, ximage, 0, 0);
191 cmodel_transfer(frame->get_rows(),
208 frame->get_color_model(),
216 int BC_Capture::get_top_w()
218 Screen *screen_ptr = XDefaultScreenOfDisplay(display);
219 return WidthOfScreen(screen_ptr);
222 int BC_Capture::get_top_h()
224 Screen *screen_ptr = XDefaultScreenOfDisplay(display);
225 return HeightOfScreen(screen_ptr);