1 /*****
2 * Xnee's Not an Event Emulator
3 *
4 * Xnee enables recording and replaying of X protocol data
5 *
6 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2013
7 * Henrik Sandklef
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 3
12 * of the License, or any later version.
13 *
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Boston,
23 * MA 02110-1301, USA.
24 ****/
25
26
27 #include "libxnee/xnee.h"
28 #include "libxnee/xnee_window.h"
29 #include "libxnee/print_varargs.h"
30 #include "libxnee/print.h"
31 #include "libxnee/xnee_alloc.h"
32 #include "libxnee/xnee_setget.h"
33
34 /*
35 * In this file the following two words are frequent enough
36 * to let their usage be explained:
37 * session - information read from session file
38 * received - information as received during replay from RECORD
39 */
40
41 #define XNEE_DEBUG_WINDOW_CODE 1
42 #ifdef XNEE_DEBUG_WINDOW_CODE
43 #define XNEE_WINDOW_DEBUG(a) printf a
44 #else
45 #define XNEE_WINDOW_DEBUG(a)
46 #endif
47
48 #define XNEE_WINDOW_BUFFER_SIZE 10
49 static int received_index = 0;
50 static int session_index = 0;
51
52 xnee_win_pos received_windows[XNEE_WINDOW_BUFFER_SIZE];
53 xnee_win_pos session_windows[XNEE_WINDOW_BUFFER_SIZE];
54
55 static int
xnee_window_print_lists(void)56 xnee_window_print_lists(void)
57 {
58 int i ;
59
60 fprintf (stderr,"---- List of stored window --- \n");
61 fprintf (stderr,"|\n");
62 fprintf (stderr,"| -- Session -- \n");
63 for (i=0; ( i<session_index ) && (i<XNEE_WINDOW_BUFFER_SIZE ) ;i++)
64 {
65 fprintf (stderr,"| %d 0x%X %d %d '%s'\n",
66 i,
67 session_windows[i].window,
68 session_windows[i].x,
69 session_windows[i].y,
70 session_windows[i].name?session_windows[i].name:"NO NAME");
71 }
72 fprintf (stderr,"|\n");
73 fprintf (stderr,"| -- Received --\n");
74 for (i=0;( i<received_index ) && (i<XNEE_WINDOW_BUFFER_SIZE ) ;i++)
75 {
76 fprintf (stderr,"| %d 0x%X %d %d '%s'\n",
77 i,
78 received_windows[i].window,
79 received_windows[i].x,
80 received_windows[i].y,
81 received_windows[i].name?received_windows[i].name:"NO NAME");
82 }
83 fprintf (stderr,"--- End of list of windows ....\n");
84 fprintf (stderr,"\n");
85
86 return XNEE_OK;
87 }
88
89
90 int
xnee_window_add_attribute_impl(xnee_data * xd,XWindowAttributes * attributes,Window win,Window parent,int where)91 xnee_window_add_attribute_impl(xnee_data *xd,
92 XWindowAttributes *attributes,
93 Window win,
94 Window parent,
95 int where)
96 {
97 xnee_win_pos xwp;
98 char *win_name;
99
100 xwp.x = attributes->x;
101 xwp.y = attributes->y;
102 xwp.width = attributes->width;
103 xwp.height = attributes->height;
104 xwp.window = win;
105 xwp.parent = parent;
106
107 if (where == XNEE_WINDOW_RECEIVED)
108 {
109 XFlush(xd->grab);
110
111 if (!XFetchName(xd->grab, win, &win_name))
112 { /* Get window name if any */
113 xnee_verbose((xd," window has has no name\n"));
114 win_name=NULL;
115 }
116 else if (win_name)
117 {
118 xnee_verbose((xd," window has has name '%s'\n", win_name));
119 }
120 xwp.name = win_name;
121 }
122 else
123 {
124 xwp.name = NULL;
125 }
126
127 return xnee_window_add_impl(xd, &xwp, where);
128 }
129
130
131 int
xnee_window_add_impl(xnee_data * xd,xnee_win_pos * xwp,int where)132 xnee_window_add_impl(xnee_data *xd,
133 xnee_win_pos *xwp,
134 int where)
135 {
136 xnee_win_pos *ptr;
137 int index ;
138
139 xnee_verbose((xd, "---> xnee_window_add_impl\n"));
140
141 switch ( where )
142 {
143 case XNEE_WINDOW_RECEIVED:
144 index = received_index;
145 ptr = &received_windows[received_index];
146 break;
147 case XNEE_WINDOW_SESSION:
148 index = session_index;
149 ptr = &session_windows[session_index];
150 break;
151 default:
152 return XNEE_WINDOW_POS_ADJ_ERROR;
153 }
154
155
156 if ( index >= XNEE_WINDOW_BUFFER_SIZE )
157 {
158 xnee_verbose ((xd, "<--- xnee_window_add_impl ... error\n"));
159 return XNEE_WINDOW_POS_ADJ_ERROR;
160 }
161
162
163 memcpy(ptr,
164 xwp,
165 sizeof(xnee_win_pos));
166
167 if ( where == XNEE_WINDOW_RECEIVED )
168 {
169 received_index++;
170 }
171 else
172 {
173 session_index++;
174 }
175
176 xnee_verbose((xd, "<--- xnee_window_add_impl\n"));
177 return XNEE_OK;
178 }
179
180
181 #ifdef CRAP
182 int
xnee_window_add_read(xnee_data * xd,xnee_win_pos * xwp)183 xnee_window_add_read(xnee_data *xd,
184 xnee_win_pos *xwp)
185 {
186 xnee_win_pos *ptr;
187
188 xnee_verbose((xd, "---> xnee_window_add_read\n"));
189
190 if ( session_index >= XNEE_WINDOW_BUFFER_SIZE )
191 {
192 xnee_verbose((xd, "<--- xnee_window_add_read ... error\n"));
193 return XNEE_WINDOW_POS_ADJ_ERROR;
194 }
195
196
197 ptr = &session_windows[session_index];
198
199 ptr->rel_x = xwp->rel_x;
200 ptr->rel_y = xwp->rel_y;
201 ptr->x = xwp->x;
202 ptr->y = xwp->y;
203 ptr->height = xwp->height;
204 ptr->width = xwp->width;
205 ptr->window = xwp->window;
206
207 if ( where == XNEE_WINDOW_RECEIVED )
208 {
209 received_index++;
210 }
211 else
212 {
213 session_index++;
214 }
215
216 xnee_verbose((xd, "<--- xnee_window_add_impl\n"));
217 return XNEE_OK;
218 }
219 #endif /* CRAP? */
220
221
222 int
xnee_window_add_read(xnee_data * xd,xnee_win_pos * xwp)223 xnee_window_add_read(xnee_data *xd,
224 xnee_win_pos *xwp)
225 {
226 xnee_win_pos *ptr;
227
228 xnee_verbose((xd, "---> xnee_window_add_read\n"));
229
230 if ( session_index >= XNEE_WINDOW_BUFFER_SIZE )
231 {
232 xnee_verbose((xd, "<--- xnee_window_add_read ... error\n"));
233 return XNEE_WINDOW_POS_ADJ_ERROR;
234 }
235
236
237 ptr = &session_windows[session_index];
238
239 ptr->x = xwp->x;
240 ptr->y = xwp->y;
241 ptr->height = xwp->height;
242 ptr->width = xwp->width;
243
244 session_index++;
245
246 xnee_verbose((xd, "<--- xnee_window_add_read\n"));
247 return XNEE_OK;
248 }
249
250
251 static int
xnee_window_remove_window(xnee_data * xd,int rec_idx,int ses_idx)252 xnee_window_remove_window(xnee_data *xd, int rec_idx, int ses_idx)
253 {
254 int i ;
255
256 xnee_verbose((xd,"xnee_window_remove_window recorded:%d session:%d\n",
257 rec_idx, ses_idx));
258
259 for (i=rec_idx; i<XNEE_WINDOW_BUFFER_SIZE;i++)
260 {
261 /* XNEE_WINDOW_DEBUG(("Rem rece pos %d (%s,%d) and putting pos %d (%s) \n",
262 i, received_windows[i].name,received_windows[i].window,
263 i+1, received_windows[i+1].name));
264 */
265 XNEE_FREE_IF_NOT_NULL(received_windows[i].name);
266 memcpy(&received_windows[i],
267 &received_windows[i+1],
268 sizeof(xnee_win_pos));
269 if (received_windows[i+1].window==0)
270 {
271 break;
272 }
273
274 }
275
276 for (i=ses_idx; i<XNEE_WINDOW_BUFFER_SIZE;i++)
277 {
278 /* XNEE_WINDOW_DEBUG(("Rem sess pos %d (%s,%d) and putting pos %d (%s) \n",
279 i, session_windows[i].name,session_windows[i].window,
280 i+1, session_windows[i+1].name));
281 */
282 if (session_windows[i].name!=NULL)
283 {
284 XFree(session_windows[i].name);
285 }
286 memcpy(&session_windows[i],
287 &session_windows[i+1],
288 sizeof(xnee_win_pos));
289 if (session_windows[i+1].window==0)
290 {
291 break;
292 }
293
294 }
295 session_index--;
296 received_index--;
297
298 return XNEE_OK;
299 }
300
301
302
303
304 int
xnee_window_try_move(xnee_data * xd)305 xnee_window_try_move(xnee_data *xd)
306 {
307 int ret = XNEE_OK;
308 xnee_win_pos *sess_ptr;
309 xnee_win_pos *rec_ptr;
310
311 int pos_x;
312 int pos_y;
313 int rx ;
314 int ry ;
315 int diff_x=0;
316 int diff_y=0;
317 int nr_of_moves = 0;
318 XWindowAttributes win_attributes;
319 Window child;
320
321 printf (" MAX: %d\n", xnee_get_max_nr_of_moves(xd));
322
323 xnee_verbose((xd, "Trying to move window %d %d \n",
324 session_index,
325 received_index));
326
327 if (xnee_is_verbose(xd))
328 {
329 xnee_window_print_lists();
330 }
331
332 /*
333 * If we haven't read (from file) and received (from RECORD)
334 * then there we lack info on how to move the new window...
335 * return....
336 */
337 if ( (session_index==0) || (received_index==0) )
338 {
339 return XNEE_OK;
340 }
341
342 XNEE_VERBOSE_MARK();
343
344 xnee_verbose((xd, "Trying to move window 1\n"));
345 /*
346 * OK, we have read info on saved window and we have
347 * a window to apply that info on, let's do it.
348 */
349 sess_ptr = &session_windows[session_index-1];
350 rec_ptr = &received_windows[received_index-1];
351
352
353 if ( rec_ptr->window == 0 )
354 {
355 return XNEE_WINDOW_POS_ADJ_ERROR;
356 }
357
358 XNEE_VERBOSE_MARK();
359 XGetWindowAttributes(xd->grab,
360 rec_ptr->window,
361 &win_attributes);
362
363 XTranslateCoordinates (xd->grab,
364 rec_ptr->window,
365 win_attributes.root,
366 win_attributes.border_width,
367 win_attributes.border_width,
368 &rx,
369 &ry,
370 &child);
371
372
373 if ( (sess_ptr->x==rx) && (sess_ptr->y==ry) )
374 {
375 XNEE_WINDOW_DEBUG(("Windows are already loacted correctly :) %d %d %d %d\n",
376 sess_ptr->x,
377 rx,
378 sess_ptr->y,
379 ry));
380 xnee_window_remove_window(xd, received_index-1, session_index-1);
381 return XNEE_OK;
382 }
383
384 xnee_verbose((xd, "XMoveWindow(%p,0x%X, %u,%u)\n",
385 (void*)xd->grab,
386 rec_ptr->window,
387 (unsigned int)sess_ptr->x ,
388 (unsigned int)sess_ptr->y ));
389 XNEE_WINDOW_DEBUG(("XMoveWindow(%p,0x%X, %u,%u)\n",
390 (void*)xd->grab,
391 rec_ptr->window,
392 (unsigned int)sess_ptr->x ,
393 (unsigned int)sess_ptr->y ));
394 XMoveWindow(xd->grab,
395 rec_ptr->window,
396 sess_ptr->x ,
397 sess_ptr->y );
398
399 XFlush(xd->grab);
400 usleep(50*1000);
401
402 XGetWindowAttributes(xd->grab,
403 rec_ptr->window,
404 &win_attributes);
405
406 XTranslateCoordinates (xd->grab,
407 rec_ptr->window,
408 win_attributes.root,
409 win_attributes.border_width,
410 win_attributes.border_width,
411 &rx,
412 &ry,
413 &child);
414
415 while ( nr_of_moves<xnee_get_max_nr_of_moves(xd))
416 {
417
418
419 /* requested - actual - frame */
420 XNEE_VERBOSE_MARK();
421
422 diff_x = sess_ptr->x - rx ;
423 diff_y = sess_ptr->y - ry ;
424
425 XNEE_WINDOW_DEBUG(("Requested Actual diff attrib window=0x%X (%d try)\n", rec_ptr->window, nr_of_moves));
426 XNEE_WINDOW_DEBUG((" %.3d %.3d %.2d %d\n",
427 sess_ptr->x , rx , diff_x, win_attributes.x));
428 XNEE_WINDOW_DEBUG((" %.3d %.3d %.2d %d\n",
429 sess_ptr->y , ry , diff_y, win_attributes.y));
430 XNEE_WINDOW_DEBUG(("\n"));
431
432 if ( !diff_x && !diff_y )
433 {
434
435
436 xnee_window_remove_window(xd, received_index-1, session_index-1);
437 xnee_verbose((xd,"leaving ..... all (%d %d) is ok\n", diff_x, diff_y));
438 break;
439 }
440
441 pos_x = sess_ptr->x + diff_x ;
442 pos_y = sess_ptr->y + diff_y ;
443
444 xnee_verbose((xd, "XMoveWindow(%p,0x%X, %u,%u)\n",
445 (void*)xd->grab,
446 rec_ptr->window,
447 (unsigned int)pos_x ,
448 (unsigned int)pos_y ));
449 XNEE_WINDOW_DEBUG(("XMoveWindow(%p,0x%X, %u,%u)\n",
450 (void*)xd->grab,
451 rec_ptr->window,
452 (unsigned int)pos_x ,
453 (unsigned int)pos_y ));
454 XMoveWindow(xd->grab, rec_ptr->window, pos_x, pos_y);
455
456 XFlush(xd->grab);
457 usleep(50*1000);
458 XGetWindowAttributes(xd->grab,
459 rec_ptr->window,
460 &win_attributes);
461
462 XTranslateCoordinates (xd->grab,
463 rec_ptr->window,
464 win_attributes.root,
465 win_attributes.border_width,
466 win_attributes.border_width,
467 &rx,
468 &ry,
469 &child);
470 nr_of_moves++;
471 }
472
473 xnee_verbose((xd, "<--- xnee_window_try_move: moved %d times\n", nr_of_moves));
474 return ret;
475 }
476
477
478