void client_deliver_config(Client *c)
{
  XConfigureEvent ce;
   
  ce.type = ConfigureNotify;
  ce.event = c->window;
  ce.window = c->window;
  ce.x = c->geometry.x;
  ce.y = c->geometry.y;
  ce.width = c->geometry.width;
  ce.height = c->geometry.height;
  ce.border_width = 0;
  ce.above = None;
  ce.override_redirect = 0;
   
  dbg("%s() to %s  x: %i , y: %i w: %i h: %i \n", 
      __func__, c->title_string, ce.x, ce.y, ce.width, ce.height);

  XSendEvent(dpy, c->window, False,
	     StructureNotifyMask, (XEvent *)&ce);
}


void
wm_handle_configure_request (XConfigureRequestEvent *e )
{
   Client         *c = client_of_window(e->window);
   XWindowChanges  xwc;

   unsigned long   value_mask = e->value_mask;
   int             req_x      = e->x;
   int             req_y      = e->y;
   int             req_w      = e->width;
   int             req_h      = e->height;

   Bool            want_activate = False;

   /* TODO: Double check ICCCM on this code. 
    *       see http://tronche.com/gui/x/icccm/sec-4.html#s-4.1.5
    *       Only send synthetic configure notify on no change.
    *
    */  

   if (!c ) 
     {
       /* Dont know any thing about this window. Let it have what it 
        * wants and leave. 
        */
       dbg("%s() could find source client %ix%i\n", __func__,
	   										e->width, e->height);
       xwc.x       = req_x;
       xwc.y       = req_y;
       xwc.width   = req_w;
       xwc.height  = req_h;
       xwc.sibling = e->above;
       xwc.stack_mode = e->detail;
       XConfigureWindow(dpy, e->window, e->value_mask, &xwc);
       return;
     }

   /* Process exactly what changes have been reuested */

   if (!(value_mask & CWWidth))  req_w = c->geometry.width;
   if (!(value_mask & CWHeight)) req_h = c->geometry.height;
   
   if (e->x <= 0 || !(value_mask & CWX)) req_x = c->geometry.x;
   if (e->y <= 0 || !(value_mask & CWY)) req_y = c->geometry.y;

   dbg("%s() for win %s - have w: %i vs %i, h: %i" 
       "vs %i, x: %i vs %i, y: %i vs %i,\n", 
       __func__, c->title_string, c->geometry.height, req_h, c->geometry.width, 
       req_w, c->geometry.x, req_x, req_y, e->y );

   /* Deal with raising - needs work, not sure if anything really
    * relies on this / or how it fits with mb. 
    *
    * Wins can use _NET_ACTIVATE_WINDOW to raise themselse. 
    * Dialogs should be able to raise / lower theme selves ? 
    */
   if (value_mask & (CWSibling|CWStackMode))
     {
       /* e->above  is sibling 
        * e->detail is stack_mode 
	*/

       Client *sibling = client_of_window(w, e->window);

       dbg("%s() value_mask & (CWSibling|CWStackMode) sibling is %s (%li vs %li\n",
	   __func__, sibling ? sibling->title_string : "unkown", e->window, c->window );

       if (sibling)
	 {
	   switch (e->detail)
	     {
	     case Above:

	       dbg("%s() (CWSibling|CWStackMode) above %s\n",
		   __func__, sibling->title_string);

	       /* Dialog 'above its self, call activate to raise it */
	       if (sibling == c && c->type == WINDOW_DIALOG)
		   want_activate = True;
	       break;
	     case Below:
	       dbg("%s() (CWSibling|CWStackMode) below %s\n",
		   __func__, sibling->title_string);
	       /* Unsupported currently clear flags */
	       value_mask &= ~(CWSibling|CWStackMode);
	       break;
	     case TopIf:    	/* What do these mean ? */
	     case BottomIf: 
	     case Opposite:
	     default:
	       dbg("%s() (CWSibling|CWStackMode) uh? %s\n",
		   __func__, sibling->title_string);
	       /* Unsupported currently clear flags */
	       value_mask &= ~(CWSibling|CWStackMode);
	       break;

	     }
	 }
       else /* Just clear the flags now to be safe */
	 value_mask &= ~(CWSibling|CWStackMode);
     }

   if (c->type == WINDOW_DOCK) 	/* Panels can move */
     {
       if ( c->geometry.height != req_h || c->geometry.width != req_w
	    || c->geometry.x != req_x || c->geometry.y != req_y )
	 {
	   Window win_tmp   = c->window;
	   xwc.width        = e->width;
	   xwc.height       = e->height;
	   xwc.x            = e->x;
	   xwc.y            = e->y;
	   xwc.border_width = 0;
	   xwc.sibling      = 0;
	   xwc.stack_mode   = e->detail;
	   
	   XConfigureWindow(dpy, e->window, value_mask, &xwc);

	   client_deliver_config(c); /* TODO: Not needed */
	   set_wm_state(c->window, WithdrawnState);

	   /* Now we destroy the window internally and re-birth it.
            * A bit of a cheat, but works.
	    */

	   XReparentWindow(dpy, c->window, w->root, e->x, e->y); 
	   client_destroy(c);
	   
	   c = client_new(w, win_tmp);
	   if (c) c->ignore_unmap++;
	   return;
        } 
     } 

   if (c->type == WINDOW_TOOLBAR) 	/* can change height */
     {
       if (req_h != c->geometry.height && !(c->state & STATE_HIDDEN))
	 {
	   int change_amount = c->geometry.height - e->height;
	   c->geometry.y += change_amount;
	   c->geometry.height = e->height;
	   c->move_resize(c);
	   wm_update_layout(w, c, change_amount); 
	   return;
	 }
     }

   if (c->type == WINDOW_DIALOG)
     {
       /* Update the size the dialog is trying to get too eventually
        * - eg toolbar/panel/input windows may dissapear and make
        *      more space available. 
        */
       if (e->width && (value_mask & CWWidth) 
	   && e->geometry.width != c->geometry.width && e->width != c->init_width)
	 c->init_width = e->width;

       if (e->height && (value_mask & CWHeight) 
	   && e->height != c->geometry.height && e->height != c->init_height)
	 c->init_height = e->height;

       /* If any changes, now make them fit it into avaialable area. */

       if (req_x != c->x || req_y != c->y 
	   || req_w != c->width || req_h != c->geometry.height
	   || want_activate)
	 {
	   Bool want_fake_configure = False;
	   
	   dialog_constrain_geometry(c, &req_x, &req_y, &req_w, &req_h);

	   if (c->width == req_w && c->geometry.height == req_h)
	     want_fake_configure = True; 

	   /* make sure buttons get repositioned */
	   if (c->geometry.width != req_w)
	     client_buttons_delete_all(c);

	   /* TODO: fix composite for this */
	   // comp_engine_client_hide(c->wm, c);
	   
	   xwc.width  = c->geometry.width  = req_w;
	   xwc.height = c->geometry.height = req_h;
	   xwc.x      = c->geometry.x      = req_x;
	   xwc.y      = c->geometry.y      = req_y; 

	   /* ICCCM says if window only moved - not size change,
            * then we send a fake one too.
	    */
	   if (want_fake_configure)
	     client_deliver_config(c);

	   /* Client wants to be raised to top of stack */
	   if (want_activate)
	       client_raise(c);
	   
	   dialog_client_move_resize(c);
	   dialog_client_redraw(c, False);

	   /* make sure composite does any needed updates */
	   comp_engine_client_configure(w, c);
	   comp_engine_client_show(w, c);

	   return;
	 }
     }

   /* Nothing has changed but ICCCM still send synthetic config 
    * Code should fall back to this.
    */
   client_deliver_config(c);
}




