plug leaks, leaker tweaks, lang for effect info, c41 spiffs, wm probe tweaks
[goodguy/history.git] / cinelerra-5.1 / 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 = 0;  unsigned int ncwin = 0;
68         Window cwin = 0, pwin = 0, root = 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         int nx = px, ny = py;  pwin = win;
75         for( int i=5; --i>=0; ) {
76                 win = pwin;  root = 0;  pwin = 0;  pcwin = 0;  ncwin = 0;
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                 BC_DisplayInfo display_info;
190                 display_info.test_window(left_border, top_border,
191                         auto_reposition_x, auto_reposition_y, 100, 100);
192                 right_border = left_border;
193                 bottom_border = left_border;
194 //printf("BC_DisplayInfo::init_borders border=%d %d auto=%d %d\n",
195 //  left_border, top_border, auto_reposition_x, auto_reposition_y);
196         }
197 }
198
199
200 int BC_DisplayInfo::get_top_border()
201 {
202         init_borders();
203         return top_border;
204 }
205
206 int BC_DisplayInfo::get_left_border()
207 {
208         init_borders();
209         return left_border;
210 }
211
212 int BC_DisplayInfo::get_right_border()
213 {
214         init_borders();
215         return right_border;
216 }
217
218 int BC_DisplayInfo::get_bottom_border()
219 {
220         init_borders();
221         return bottom_border;
222 }
223
224 void BC_DisplayInfo::init_window(const char *display_name, int show_error)
225 {
226         if(display_name && display_name[0] == 0) display_name = NULL;
227
228 #ifdef SINGLE_THREAD
229         display = BC_Display::get_display(display_name);
230 #else
231
232 // This function must be the first Xlib
233 // function a multi-threaded program calls
234         XInitThreads();
235
236         if((display = XOpenDisplay(display_name)) == NULL)
237         {
238                 if(!show_error) return;
239                 fprintf(stderr,_("BC_DisplayInfo::init_window: cannot open display \"%s\".\n"),
240                         display_name ? display_name : "");
241                 if(getenv("DISPLAY") == NULL)
242                         fprintf(stderr, _("'DISPLAY' environment variable not set.\n"));
243                 if((display = XOpenDisplay(0)) == NULL) {
244                         fprintf(stderr,_("BC_DisplayInfo::init_window: cannot connect to X server.\n"));
245                         exit(1);
246                 }
247         }
248 #endif // SINGLE_THREAD
249
250 #ifdef SINGLE_THREAD
251         BC_Display::lock_display("BC_DisplayInfo::init_window");
252 #endif
253         screen = DefaultScreen(display);
254         rootwin = RootWindow(display, screen);
255         vis = DefaultVisual(display, screen);
256         default_depth = DefaultDepth(display, screen);
257 #ifdef SINGLE_THREAD
258         BC_Display::unlock_display();
259 #endif // SINGLE_THREAD
260 }
261
262
263 int BC_DisplayInfo::get_root_w()
264 {
265 #ifdef SINGLE_THREAD
266         BC_Display::lock_display("BC_DisplayInfo::get_root_w");
267 #endif
268         Screen *screen_ptr = XDefaultScreenOfDisplay(display);
269         int result = WidthOfScreen(screen_ptr);
270 #ifdef SINGLE_THREAD
271         BC_Display::unlock_display();
272 #endif
273         return result;
274 }
275
276 int BC_DisplayInfo::get_root_h()
277 {
278 #ifdef SINGLE_THREAD
279         BC_Display::lock_display("BC_DisplayInfo::get_root_h");
280 #endif
281         Screen *screen_ptr = XDefaultScreenOfDisplay(display);
282         int result = HeightOfScreen(screen_ptr);
283 #ifdef SINGLE_THREAD
284         BC_Display::unlock_display();
285 #endif
286         return result;
287 }
288
289 int BC_DisplayInfo::get_abs_cursor_x()
290 {
291         int abs_x, abs_y, win_x, win_y;
292         unsigned int temp_mask;
293         Window temp_win;
294
295 #ifdef SINGLE_THREAD
296         BC_Display::lock_display("BC_DisplayInfo::get_abs_cursor_x");
297 #endif
298         XQueryPointer(display,
299            rootwin,
300            &temp_win,
301            &temp_win,
302        &abs_x,
303            &abs_y,
304            &win_x,
305            &win_y,
306            &temp_mask);
307 #ifdef SINGLE_THREAD
308         BC_Display::unlock_display();
309 #endif
310         return abs_x;
311 }
312
313 int BC_DisplayInfo::get_abs_cursor_y()
314 {
315         int abs_x, abs_y, win_x, win_y;
316         unsigned int temp_mask;
317         Window temp_win;
318
319 #ifdef SINGLE_THREAD
320         BC_Display::lock_display("BC_DisplayInfo::get_abs_cursor_y");
321 #endif
322         XQueryPointer(display,
323            rootwin,
324            &temp_win,
325            &temp_win,
326        &abs_x,
327            &abs_y,
328            &win_x,
329            &win_y,
330            &temp_mask);
331 #ifdef SINGLE_THREAD
332         BC_Display::unlock_display();
333 #endif
334         return abs_y;
335 }
336
337
338 int BC_DisplayInfo::get_screen_count()
339 {
340         return XScreenCount(display);
341 }
342
343
344 const char *BC_DisplayInfo::host_display_name(const char *display_name)
345 {
346         return XDisplayName(display_name);
347 }
348