allow ffmpeg video to resample curr_pos, add bluray format
[goodguy/history.git] / cinelerra-5.0 / guicast / bcdisplayinfo.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
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
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * 
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  * 
20  */
21
22 #include "bcdisplay.h"
23 #include "bcdisplayinfo.h"
24 #include "bcsignals.h"
25 #include "bcwindowbase.h"
26 #include "clip.h"
27 #include "language.h"
28
29 #include <X11/X.h>
30 #include <X11/Xlib.h>
31 #include <X11/Xutil.h>
32 #include <unistd.h>
33
34 #define TEST_SIZE 128
35 #define TEST_DSIZE 28
36 #define TEST_SIZE2 164
37
38 int BC_DisplayInfo::top_border = -1;
39 int BC_DisplayInfo::left_border = -1;
40 int BC_DisplayInfo::bottom_border = -1;
41 int BC_DisplayInfo::right_border = -1;
42 int BC_DisplayInfo::auto_reposition_x = -1;
43 int BC_DisplayInfo::auto_reposition_y = -1;
44
45
46 BC_DisplayInfo::BC_DisplayInfo(const char *display_name, int show_error)
47 {
48         screen = -1;
49         init_window(display_name, show_error);
50 }
51
52 BC_DisplayInfo::~BC_DisplayInfo()
53 {
54 #ifndef SINGLE_THREAD
55         XCloseDisplay(display);
56 #endif
57 }
58
59
60 void BC_DisplayInfo::parse_geometry(char *geom, int *x, int *y, int *width, int *height)
61 {
62         XParseGeometry(geom, x, y, (unsigned int*)width, (unsigned int*)height);
63 }
64
65 static void get_top_coords(Display *display, Window win, int &px,int &py, int &tx,int &ty)
66 {
67         Window *pcwin;  unsigned int ncwin;
68         Window cwin = 0, pwin = 0, root = 0;
69         int nx=0, ny=0;
70         XQueryTree(display, win, &root, &pwin, &pcwin, &ncwin);
71         if( pcwin ) XFree(pcwin);
72         XTranslateCoordinates(display, pwin, root, 0,0, &px,&py, &cwin);
73 //printf(" win=%lx, px/py=%d/%d\n", win, px,py);
74
75         for( int i=5; --i>=0; ) {
76                 win = pwin;
77                 XQueryTree(display, win, &root, &pwin, &pcwin, &ncwin);
78                 if( pcwin ) XFree(pcwin);
79                 if( pwin == root ) break;
80                 XTranslateCoordinates(display, pwin, root, 0,0, &nx,&ny, &cwin);
81 //printf(" win=%lx, nx/ny=%d/%d\n", win, nx,ny);
82         }
83         tx = nx;  ty = ny;
84 }
85
86         
87 void BC_DisplayInfo::test_window(int &x_out, 
88         int &y_out, 
89         int &x_out2, 
90         int &y_out2, 
91         int x_in, 
92         int y_in)
93 {
94 #ifdef SINGLE_THREAD
95         BC_Display::lock_display("BC_DisplayInfo::test_window");
96 #endif
97
98         x_out = 0;
99         y_out = 0;
100         int x_out1 = 0;
101         int y_out1 = 0;
102         x_out2 = 0;
103         y_out2 = 0;
104
105         unsigned long mask = CWEventMask | CWWinGravity | CWBackPixel;
106         XSetWindowAttributes attr;
107         attr.event_mask = StructureNotifyMask;
108         attr.win_gravity = SouthEastGravity;
109         attr.background_pixel = BlackPixel(display,screen);
110         Window win = XCreateWindow(display, rootwin, 
111                         x_in, y_in, TEST_SIZE, TEST_SIZE, 
112                         0, default_depth, InputOutput, 
113                         vis, mask, &attr);
114         XSizeHints size_hints;
115         XGetNormalHints(display, win, &size_hints);
116         size_hints.flags = PPosition | PSize;
117         size_hints.x = x_in;
118         size_hints.y = y_in;
119         size_hints.width = TEST_SIZE;
120         size_hints.height = TEST_SIZE;
121         XSetStandardProperties(display, win, 
122                 "x", "x", None, 0, 0, &size_hints);
123         XClearWindow(display, win);
124         XMapWindow(display, win); 
125         XFlush(display);  XSync(display, 0);  usleep(100000);
126
127         XEvent event;
128         int state = 0;
129
130         while( state < 3 ) {
131                 XNextEvent(display, &event);
132 //printf("BC_DisplayInfo::test_window 1 event=%d %d\n", event.type, XPending(display));
133                 if( event.xany.window != win ) continue;
134                 if( event.type != ConfigureNotify ) continue;
135                 Window cwin = 0;
136                 int rx = 0, ry = 0, px = 0, py = 0, tx = 0, ty = 0;
137 //printf("BC_DisplayInfo::test_window 1 state=%d x=%d y=%d w=%d h=%d bw=%d sev=%d\n",
138 //  state, event.xconfigure.x, event.xconfigure.y,
139 //  event.xconfigure.width, event.xconfigure.height,
140 //  event.xconfigure.border_width, event.xconfigure.send_event);
141                 get_top_coords(display,win, px,py, tx,ty);
142 //printf("x_in,y_in=%d,%d dx,dy=%d,%d\n", x_in,y_in, x_in-tx,y_in-ty);
143                 switch( state ) {
144                 case 0: // Get creation config
145                         XTranslateCoordinates(display, win, rootwin, 0,0, &rx,&ry, &cwin);
146                         x_out = rx - x_in;
147                         y_out = ry - y_in;
148                         XMoveResizeWindow(display, win, x_in,y_in, TEST_SIZE2,TEST_SIZE2);
149                         XFlush(display);  XSync(display, 0);  usleep(100000);
150                         ++state;
151                         break;
152                 case 1: // Get moveresize resizing
153                         XTranslateCoordinates(display, win, rootwin, 0,0, &rx,&ry, &cwin);
154                         x_out1 = px;
155                         y_out1 = py;
156                         x_in += TEST_DSIZE;  y_in += TEST_DSIZE;
157                         XMoveResizeWindow(display, win, x_in,y_in, TEST_SIZE2,TEST_SIZE2);
158                         XFlush(display);  XSync(display, 0);  usleep(100000);
159                         ++state;
160                         break;
161                 case 2: // Get moveresize move
162                         XTranslateCoordinates(display, win, rootwin, 0,0, &rx,&ry, &cwin);
163                         x_out2 = px - x_out1 - TEST_DSIZE;
164                         y_out2 = py - y_out1 - TEST_DSIZE;
165                         ++state;
166                         break;
167                 }
168         }
169 //printf("\nBC_DisplayInfo::test_window 3 x0,y0=%d,%d, x1,y1=%d,%d, x2,y2=%d,%d\n",
170 //  x_out,y_out, x_out1,y_out1, x_out2,y_out2);
171 //printf("\nx_in,y_in=%d,%d\n", x_in,y_in);
172
173         XDestroyWindow(display, win);
174         XFlush(display);
175         XSync(display, 0);
176
177         x_out = MAX(0, MIN(x_out, 48));
178         y_out = MAX(0, MIN(y_out, 48));
179
180 #ifdef SINGLE_THREAD
181         BC_Display::unlock_display();
182 #endif
183 }
184
185 void BC_DisplayInfo::init_borders()
186 {
187         if(top_border < 0)
188         {
189
190                 test_window(left_border, 
191                         top_border, 
192                         auto_reposition_x, 
193                         auto_reposition_y, 
194                         100, 100);
195                 right_border = left_border;
196                 bottom_border = left_border;
197 //printf("BC_DisplayInfo::init_borders border=%d %d auto=%d %d\n", 
198 //  left_border, top_border, auto_reposition_x, auto_reposition_y);
199         }
200 }
201
202
203 int BC_DisplayInfo::get_top_border()
204 {
205         init_borders();
206         return top_border;
207 }
208
209 int BC_DisplayInfo::get_left_border()
210 {
211         init_borders();
212         return left_border;
213 }
214
215 int BC_DisplayInfo::get_right_border()
216 {
217         init_borders();
218         return right_border;
219 }
220
221 int BC_DisplayInfo::get_bottom_border()
222 {
223         init_borders();
224         return bottom_border;
225 }
226
227 void BC_DisplayInfo::init_window(const char *display_name, int show_error)
228 {
229         if(display_name && display_name[0] == 0) display_name = NULL;
230
231 #ifdef SINGLE_THREAD
232         display = BC_Display::get_display(display_name);
233 #else
234         
235 // This function must be the first Xlib
236 // function a multi-threaded program calls
237         XInitThreads();
238
239         if((display = XOpenDisplay(display_name)) == NULL)
240         {
241                 if(!show_error) return;
242                 fprintf(stderr,_("BC_DisplayInfo::init_window: cannot open display \"%s\".\n"),
243                         display_name ? display_name : "");
244                 if(getenv("DISPLAY") == NULL)
245                         fprintf(stderr, _("'DISPLAY' environment variable not set.\n"));
246                 if((display = XOpenDisplay(0)) == NULL) {
247                         fprintf(stderr,_("BC_DisplayInfo::init_window: cannot connect to X server.\n"));
248                         exit(1);
249                 }
250         }
251 #endif // SINGLE_THREAD
252
253 #ifdef SINGLE_THREAD
254         BC_Display::lock_display("BC_DisplayInfo::init_window");
255 #endif
256         screen = DefaultScreen(display);
257         rootwin = RootWindow(display, screen);
258         vis = DefaultVisual(display, screen);
259         default_depth = DefaultDepth(display, screen);
260 #ifdef SINGLE_THREAD
261         BC_Display::unlock_display();
262 #endif // SINGLE_THREAD
263 }
264
265
266 int BC_DisplayInfo::get_root_w()
267 {
268 #ifdef SINGLE_THREAD
269         BC_Display::lock_display("BC_DisplayInfo::get_root_w");
270 #endif
271         Screen *screen_ptr = XDefaultScreenOfDisplay(display);
272         int result = WidthOfScreen(screen_ptr);
273 #ifdef SINGLE_THREAD
274         BC_Display::unlock_display();
275 #endif
276         return result;
277 }
278
279 int BC_DisplayInfo::get_root_h()
280 {
281 #ifdef SINGLE_THREAD
282         BC_Display::lock_display("BC_DisplayInfo::get_root_h");
283 #endif
284         Screen *screen_ptr = XDefaultScreenOfDisplay(display);
285         int result = HeightOfScreen(screen_ptr);
286 #ifdef SINGLE_THREAD
287         BC_Display::unlock_display();
288 #endif
289         return result;
290 }
291
292 int BC_DisplayInfo::get_abs_cursor_x()
293 {
294         int abs_x, abs_y, win_x, win_y;
295         unsigned int temp_mask;
296         Window temp_win;
297
298 #ifdef SINGLE_THREAD
299         BC_Display::lock_display("BC_DisplayInfo::get_abs_cursor_x");
300 #endif
301         XQueryPointer(display, 
302            rootwin, 
303            &temp_win, 
304            &temp_win,
305        &abs_x, 
306            &abs_y, 
307            &win_x, 
308            &win_y, 
309            &temp_mask);
310 #ifdef SINGLE_THREAD
311         BC_Display::unlock_display();
312 #endif
313         return abs_x;
314 }
315
316 int BC_DisplayInfo::get_abs_cursor_y()
317 {
318         int abs_x, abs_y, win_x, win_y;
319         unsigned int temp_mask;
320         Window temp_win;
321
322 #ifdef SINGLE_THREAD
323         BC_Display::lock_display("BC_DisplayInfo::get_abs_cursor_y");
324 #endif
325         XQueryPointer(display, 
326            rootwin, 
327            &temp_win, 
328            &temp_win,
329        &abs_x, 
330            &abs_y, 
331            &win_x, 
332            &win_y, 
333            &temp_mask);
334 #ifdef SINGLE_THREAD
335         BC_Display::unlock_display();
336 #endif
337         return abs_y;
338 }
339
340
341 int BC_DisplayInfo::get_screen_count()
342 {
343         return XScreenCount(display);
344 }
345
346
347 const char *BC_DisplayInfo::host_display_name(const char *display_name)
348 {
349         return XDisplayName(display_name);
350 }
351