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