4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
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.
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.
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
22 #include "bcdisplay.h"
23 #include "bcdisplayinfo.h"
24 #include "bcsignals.h"
25 #include "bcwindowbase.h"
31 #include <X11/Xutil.h>
36 #define TEST_SIZE2 164
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;
46 BC_DisplayInfo::BC_DisplayInfo(const char *display_name, int show_error)
49 init_window(display_name, show_error);
52 BC_DisplayInfo::~BC_DisplayInfo()
55 XCloseDisplay(display);
60 void BC_DisplayInfo::parse_geometry(char *geom, int *x, int *y, int *width, int *height)
62 XParseGeometry(geom, x, y, (unsigned int*)width, (unsigned int*)height);
65 static void get_top_coords(Display *display, Window win, int &px,int &py, int &tx,int &ty)
67 Window *pcwin; unsigned int ncwin;
68 Window cwin = 0, pwin = 0, root = 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);
75 for( int i=5; --i>=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);
87 void BC_DisplayInfo::test_window(int &x_out,
95 BC_Display::lock_display("BC_DisplayInfo::test_window");
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,
114 XSizeHints size_hints;
115 XGetNormalHints(display, win, &size_hints);
116 size_hints.flags = PPosition | PSize;
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);
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;
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);
144 case 0: // Get creation config
145 XTranslateCoordinates(display, win, rootwin, 0,0, &rx,&ry, &cwin);
148 XMoveResizeWindow(display, win, x_in,y_in, TEST_SIZE2,TEST_SIZE2);
149 XFlush(display); XSync(display, 0); usleep(100000);
152 case 1: // Get moveresize resizing
153 XTranslateCoordinates(display, win, rootwin, 0,0, &rx,&ry, &cwin);
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);
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;
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);
173 XDestroyWindow(display, win);
177 x_out = MAX(0, MIN(x_out, 48));
178 y_out = MAX(0, MIN(y_out, 48));
181 BC_Display::unlock_display();
185 void BC_DisplayInfo::init_borders()
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);
200 int BC_DisplayInfo::get_top_border()
206 int BC_DisplayInfo::get_left_border()
212 int BC_DisplayInfo::get_right_border()
218 int BC_DisplayInfo::get_bottom_border()
221 return bottom_border;
224 void BC_DisplayInfo::init_window(const char *display_name, int show_error)
226 if(display_name && display_name[0] == 0) display_name = NULL;
229 display = BC_Display::get_display(display_name);
232 // This function must be the first Xlib
233 // function a multi-threaded program calls
236 if((display = XOpenDisplay(display_name)) == NULL)
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"));
248 #endif // SINGLE_THREAD
251 BC_Display::lock_display("BC_DisplayInfo::init_window");
253 screen = DefaultScreen(display);
254 rootwin = RootWindow(display, screen);
255 vis = DefaultVisual(display, screen);
256 default_depth = DefaultDepth(display, screen);
258 BC_Display::unlock_display();
259 #endif // SINGLE_THREAD
263 int BC_DisplayInfo::get_root_w()
266 BC_Display::lock_display("BC_DisplayInfo::get_root_w");
268 Screen *screen_ptr = XDefaultScreenOfDisplay(display);
269 int result = WidthOfScreen(screen_ptr);
271 BC_Display::unlock_display();
276 int BC_DisplayInfo::get_root_h()
279 BC_Display::lock_display("BC_DisplayInfo::get_root_h");
281 Screen *screen_ptr = XDefaultScreenOfDisplay(display);
282 int result = HeightOfScreen(screen_ptr);
284 BC_Display::unlock_display();
289 int BC_DisplayInfo::get_abs_cursor_x()
291 int abs_x, abs_y, win_x, win_y;
292 unsigned int temp_mask;
296 BC_Display::lock_display("BC_DisplayInfo::get_abs_cursor_x");
298 XQueryPointer(display,
308 BC_Display::unlock_display();
313 int BC_DisplayInfo::get_abs_cursor_y()
315 int abs_x, abs_y, win_x, win_y;
316 unsigned int temp_mask;
320 BC_Display::lock_display("BC_DisplayInfo::get_abs_cursor_y");
322 XQueryPointer(display,
332 BC_Display::unlock_display();
338 int BC_DisplayInfo::get_screen_count()
340 return XScreenCount(display);
344 const char *BC_DisplayInfo::host_display_name(const char *display_name)
346 return XDisplayName(display_name);