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