//
// Copyright (C) 1999-2004 Toshikaz Hirabayashi
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// TOSHIKAZ HIRABAYASHI BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// Except as contained in this notice, the name of Toshikaz Hirabayashi shall
// not be used in advertising or otherwise to promote the sale, use or other
// dealings in this Software without prior written authorization from
// Toshikaz Hirabayashi.

#include <X11/Intrinsic.h>
#include <WSCdevice.h>
#include <WSCimageSet.h>
#include <WSCcolorSet.h>
#include <WSDtimer.h>
#include <WSCbase.h>
#include <WSDmouse.h>
#include <WSClocaleSet.h>
#include <x11/WSxcom.h>
#include <x11/WSDxwinDev.h>
#include <x11/WSDxappDev.h>
#include <x11/WSDxdraw.h>
#include <X11/Shell.h>
#include <X11/StringDefs.h>
#include <form.h>

#if 1 //UNICODE
#include <xunicode.h>
#endif //UNICODE

WSMFclassInit(WSDxwinDev,WSDxformDev);
WSDdev* _wsdxwindev_init_(){
  return new WSDxwinDev();
}

class _WSDxwinDev_init_ {
  public:_WSDxwinDev_init_(){
     WSGIappDevice()->setCreateHandler("windowDev",_wsdxwindev_init_);
  };
};
static _WSDxwinDev_init_ _init_to_run_WSDxwinDev_;
static Atom wm_protocols = 0;
static Atom wm_delete = 0;

WSDxwinDev::WSDxwinDev(){
  _swidget  = 0;
  _widget  = 0;
  _title_bar_style = 0;
  _no_frame = 0;
  _no_frame_first_time = 0;
  _requested_top = 0;
  _transient = False;
  _top_float = 0;
  _modal = 0;
  _sizehints = NULL;
  _title_bar = 0;
}

WSDxwinDev::~WSDxwinDev(){
  destroyWindow();
}

WSDdev* WSDxwinDev::getVisibleParentDev(){
  return this;
}

long WSDxwinDev::setValue(long kind,void* data){
  WSDwindowDev::setValue(kind,data);
  Arg args[4];
  char val;
  long vl;
  char* vstr;
  WSDcolor* color;
  WSDimage* image;
  XWindowChanges wc;
  WSCbase* pparent;
  WSDxwinDev*  pdev;
  Widget    pwidget;
  WSCbool   fl;
  WSCstring tmpstr;
  switch(kind){
    case WSDEV_X: 
             if (getVisible() == False){
               _diff_x = 0;
             }
             if (_swidget != 0){
               if (getVisible() != False){
                 XtSetArg(args[0],XtNx,*(short*)data);
                 XtSetValues((Widget)_swidget,args,1);
               }
             }
             break;
    case WSDEV_Y:
             if (getVisible() == False){
               _diff_y = 0;
             }
             if (_swidget != 0){
               if (getVisible() != False){
                 XtSetArg(args[0],XtNy,*(short*)data);
                 XtSetValues((Widget)_swidget,args,1);
               }
             }
             break;
    case WSDEV_WIDTH:
             if (_swidget != 0){
               if (getVisible() != False && *(WSCushort*)data > 0){

                 WSCushort val;
                 XtSetArg(args[0],XtNwidth,&val);
                 XtGetValues((Widget)_swidget,args,1);
                 if ( *(WSCushort*)data != val){
                   XtSetArg(args[0],XtNwidth,*(WSCushort*)data);
                   XtSetValues((Widget)_swidget,args,1);
                 }
               }
             }
             break;
    case WSDEV_HEIGHT:
WSMFtrace("WSCxwinDev::setValue height=%d _w_h=%d\n",*(WSCushort*)data,_w_h);
             if (_swidget != 0){
               if (getVisible() != False && *(WSCushort*)data > 0){
                 WSCushort val;
                 XtSetArg(args[0],XtNheight,&val);
                 XtGetValues((Widget)_swidget,args,1);
                 if ( *(WSCushort*)data != val){
                   XtSetArg(args[0],XtNheight,*(WSCushort*)data);
                   XtSetValues((Widget)_swidget,args,1);
                 }
               }
             }
             break;
    case WSDEV_BACKCOLOR:
             _bg = *(short*)data;
             color = WSGIappColorSet()->getColor(*(short*)data);
             if (color != NULL && _widget != NULL){
               XtSetArg(args[0],XtNbackground,color->getValue1());
               XtSetValues((Widget)_widget,args,1);
             }
             break;
    case WSDEV_BACK_PIXMAP:
             _bg_pix = *(short*)data;
             if (_widget == NULL){
               break;
             }
             if (*(short*)data == -2 ){
               XtSetArg(args[0],XtNbackgroundPixmap,0);
               XtSetValues((Widget)_widget,args,1);
             }else
             if (*(short*)data == -1 ){
               XtSetArg(args[0],XtNbackgroundPixmap,UNSPECIFIED_PIXMAP);
               XtSetValues((Widget)_widget,args,1);
             }else{
               image = WSGIappImageSet()->getImage(*(short*)data);
               if (image != NULL){
                 if (image->getValue1() == -1){
                   XtSetArg(args[0],XtNbackgroundPixmap,UNSPECIFIED_PIXMAP);
                 }else{
                   XtSetArg(args[0],XtNbackgroundPixmap,image->getValue1());
                 }
                 XtSetValues((Widget)_widget,args,1);
               }
             }
             break;
    case WSDEV_TITLE_BAR:
             val = *(char*)data;
             _title_bar = val;
             switch(val){
               case WS_NO_TITLE:   vl = 0; break;
               case WS_FULL_TITLE: vl = 1; break;
               case WS_ONLY_TITLE: vl = 8; break;
               case WS_MINI_BTN:   vl = 40; break;
               case WS_MAX_BTN:    vl = 104; break;
               case WS_FRAME:      vl = 4; break;
               default: vl = 1;
             };
#if 0 //DEVELOP
             if ((Widget)_widget != (Widget)NULL){
               XtSetArg(args[0],"mwmDecorations",vl);
               XtSetValues((Widget)_swidget,args,1);
             }
#endif
             _title_bar_style = vl;
             if (vl == 0){
               _diff_x = 0;
               _diff_y = 0;
             }
             break;
    case WSDEV_TITLE_STRING:
             vstr = (char*)data;
             if ((Widget)_swidget != (Widget)NULL){
               tmpstr.setString(vstr,WSGIappLocaleSet()->getDefaultEncoding());
               XtSetArg(args[0],XtNtitle,
                   tmpstr.getString(WSGIappLocaleSet()->getSystemLocaleEncoding()));
               XtSetValues((Widget)_swidget,args,1);
             }

             break;
    case WSDEV_NO_FRAME:  
             _top_float = False;
             if (*(char*)data == False &&
                  _no_frame != False &&
                  (Widget)_swidget != (Widget)NULL){
               //In this case,if it sets this data,it will be curruped.
               break;
             }
             _no_frame = *(char*)data;
             if (_no_frame != False && (Widget)_swidget != (Widget)NULL){
               XtSetArg(args[0],XtNoverrideRedirect,True);
               XtSetValues((Widget)_swidget,args,1);
               _no_frame_first_time = True;
             }else if (_no_frame == True && (Widget)_swidget == (Widget)NULL){
               _no_frame_first_time = True;
             }else if (_no_frame == False && (Widget)_swidget == (Widget)NULL){
               _no_frame_first_time = False;
             }
             break;
    case WSDEV_POPUP_PARENT: 
             pparent = (WSCbase*)data;
             if (pparent != NULL){
               if (pparent->getowndev() != NULL ){
                 pdev = (WSDxwinDev*)pparent->getowndev()->cast("WSDxwinDev");
                 if (pdev != NULL){
                   pwidget = pdev->_swidget;
                   if ( (Widget)_swidget != (Widget)NULL && pwidget != (Widget)NULL){
                     XtSetArg(args[0],XtNtransient,True);
                     XtSetArg(args[1],XtNtransientFor,pwidget);
                     XtSetValues(_swidget,args,2);
                     _transient = True;
                   }
                 }
               }
             }else if (_transient != False){
               if ( (Widget)_swidget != (Widget)NULL ){
                 XtSetArg(args[0],XtNtransient,False);
                 XtSetValues(_swidget,args,1);
                 _transient = False;
               }
             }
             break;
    case WSDEV_MAP_STATUS: 
             if (getVisible()== True){
                if (*(long*)data == WS_TOP){
                  wc.stack_mode = TopIf;
                }else{
                  wc.stack_mode = BottomIf;
                }
                if (_swidget != NULL){
                  XConfigureWindow(XtDisplay((Widget)_swidget),
                        XtWindow((Widget)_swidget),CWStackMode,&wc);
                }
             }
             break;
    case WSDEV_WIN_ACTIVE: 
             if (getVisible()== True){
                if (*(char*)data == True){
                  if (_swidget != NULL){
                    XSetInputFocus(XtDisplay((Widget)_swidget),
                                 XtWindow((Widget)_swidget),
                                 RevertToParent,CurrentTime);
                  }
                }
             }
             break;
    case WSDEV_FLOAT_ON_TOP:
             if (*(char*)data == False){
                _top_float = False;
             }else{
                _top_float = True;
             }
//printf("WSDxwinDev::setValue FLOAT_ON_TOP %d\n",_top_float);
             break;
    case WSDEV_GRAB_POINTER:
             if (_widget == NULL){
               break;
             }
             fl = *(WSCbool*)data;
             if (fl != False){
               XGrabPointer(XtDisplay(_widget),XtWindow(_widget),False,
                            ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
                            GrabModeAsync,GrabModeAsync,None,None,CurrentTime);
               XGrabKeyboard(XtDisplay(_widget),XtWindow(_widget),False,
                            GrabModeAsync,GrabModeAsync,CurrentTime);
             }else{
               XUngrabPointer(XtDisplay(_widget),CurrentTime);
               XUngrabKeyboard(XtDisplay(_widget),CurrentTime);
             }
             break;
    case WSDEV_MODAL:
             if (*(char*)data == False){
               _modal = False;
             }else{
               _modal = True;
             }
             if (_widget == NULL){
               break;
             }
//printf("WSDxwinDev::setValue modal=%d\n",_modal);
             XtSetArg(args[0],"dialogStyle",_modal);
             XtSetValues(_swidget,args,1);
             break;
    case WSDEV_WINDOW_STATE:
             vl = *(long*)data;
             if (_swidget != NULL){
               if (getVisible() == False){
                 return WS_ERR;
               }
               if (vl == WS_WINDOW_MINIMIZE){
                 XIconifyWindow(XtDisplay(_swidget),XtWindow(_swidget), 0);
               }else{
                 XMapWindow(XtDisplay(_swidget),XtWindow(_swidget));
               }
               return WS_NO_ERR;
             }else{
               return WS_ERR;
             }
    case WSDEV_MOUSE_NO:
             _mno = *(WSCushort*)data;
             if (_widget != NULL && XtWindow(_widget) != 0){
               long val = WSGIappMouse()->getMouseCursor(_mouse_no);
               if (val != 0){
                 XDefineCursor(XtDisplay(_widget),XtWindow(_widget),val);
               }
             }
             return WS_ERR;
    default:
      return WS_ERR;
  }
  return WS_NO_ERR;
}

long WSDxwinDev::createWindow(){
  if (_swidget != 0){
    return WS_NO_ERR;
  }
  _no_frame_first_time = 0;
//  _top_float = False;

  short x,y;    
  WSCushort w,h;    
  getWindowSize(&x,&y,&w,&h);
  if (w == 0){
    w = 1;
  }
  if (h == 0){
    h = 1;
  }
  _transient = False;

  Arg args[10];
  long anum=0;
  XtSetArg(args[anum],XtNinput,True);anum++;
  XtSetArg(args[anum],XtNtransient,False);anum++;
  XtSetArg(args[anum],XtNx,x);anum++;
  XtSetArg(args[anum],XtNy,y);anum++;
  XtSetArg(args[anum],XtNwidth,w);anum++;
  XtSetArg(args[anum],XtNheight,h);anum++;
  XtSetArg(args[anum],"mwmDecorations",_title_bar_style);anum++;
  XtSetArg(args[anum],"dialogStyle",_modal);anum++;

  if (_title_bar_style == 0 && _no_frame == 1){
    XtSetArg(args[anum],XtNoverrideRedirect,True);anum++;
  }else{
    XtSetArg(args[anum],XtNoverrideRedirect,False);anum++;
  }
  XtSetArg(args[anum],XtNborderWidth,0); anum++;
  WSDxappDev* app = WSGIxwinAppDev(); 
  Widget parent = app->appWidget();
  WSDxformDev* xdev = getParentAreaDev();
  if (xdev != NULL){
    parent = xdev->getWidget();
  }
  Widget alt = (Widget)app->getContext2();
  if (alt != NULL){
    _swidget = alt;
  }else{
    _swidget = XtCreatePopupShell ( "wsshell", transientShellWidgetClass, parent,
               (ArgList)args, anum );
  }
  XtAddEventHandler(_swidget,StructureNotifyMask | SubstructureNotifyMask,False,(XtEventHandler)_evh_resize,this);
  XtAddEventHandler(_swidget,FocusChangeMask,False,(XtEventHandler)_evh_focus_ch,this);
  XtAddEventHandler(_swidget,NoEventMask,True,(XtEventHandler)_evh_client_message,this);

  anum =0;
  if (alt != NULL){
    app->setContext2(NULL);
    XtSetArg(args[anum],XtNwidth,_w_w);anum++;
    XtSetArg(args[anum],XtNheight,_w_h);anum++;
  }
  if (_bg != -1){
    WSDcolor* color = WSGIappColorSet()->getColor(_bg);
    if (color != NULL){
       XtSetArg(args[anum],XtNbackground,color->getValue1()); anum++;
    }
  }
  if (_bg_pix == -1){
    XtSetArg(args[anum],XtNbackgroundPixmap,UNSPECIFIED_PIXMAP); anum++;
  }else{
    WSDimage*  image = WSGIappImageSet()->getImage(_bg_pix);
    if (image != NULL){
      if (image->getValue1() == -1){
          XtSetArg(args[anum],XtNbackgroundPixmap,UNSPECIFIED_PIXMAP); anum++;
      }else{
         Pixmap pid = (Pixmap)image->getValue1();
         XtSetArg(args[anum],XtNbackgroundPixmap,pid); anum++;
      }
    }else{
      XtSetArg(args[anum],XtNbackgroundPixmap,UNSPECIFIED_PIXMAP); anum++;
    }
  }
  XtSetArg(args[anum],XtNborderWidth,0); anum++;
  _widget = XtCreateWidget ( "wswina", formWidgetClass, _swidget,args,anum);
  XtManageChild(_widget);
  XtAddEventHandler(_widget,ExposureMask,False,(XtEventHandler)_evh_expose,this);
  XtAddEventHandler(_widget,ButtonPressMask,False,(XtEventHandler)_evh_btn_press,(WSDxformDev*)this);
  XtAddEventHandler(_widget,ButtonReleaseMask,False,(XtEventHandler)_evh_btn_release,(WSDxformDev*)this);
  XtAddEventHandler(_widget,ButtonMotionMask | PointerMotionMask,False,(XtEventHandler)_evh_mouse_move,(WSDxformDev*)this);
  XtAddEventHandler(_widget,EnterWindowMask,False,(XtEventHandler)_evh_mouse_in,this);
  XtAddEventHandler(_widget,LeaveWindowMask,False,(XtEventHandler)_evh_mouse_out,(WSDxformDev*)this);
  XtAddEventHandler(_widget,KeyPressMask | KeyReleaseMask,False,(XtEventHandler)_evh_dummy,(WSDxformDev*)this);
  XtAddCallback(_widget,XtNdestroyCallback,_evh_delete2,this);
  return WS_NO_ERR;
}

long WSDxwinDev::destroyWindow(){
//printf("WSCxwinDev::destroyWindow dev=0x%x _swidget=0x%x vis=%d\n",this,_swidget,getVisible());
  WSCbool destroy = False;
  if (_widget != 0){
    XtRemoveEventHandler(_widget,ExposureMask,False,(XtEventHandler)_evh_expose,this);
    XtRemoveEventHandler(_widget,ButtonPressMask,False,(XtEventHandler)_evh_btn_press,(WSDxformDev*)this);
    XtRemoveEventHandler(_widget,ButtonReleaseMask,False,(XtEventHandler)_evh_btn_release,(WSDxformDev*)this);
    XtRemoveEventHandler(_widget,ButtonMotionMask | PointerMotionMask,False,(XtEventHandler)_evh_mouse_move,(WSDxformDev*)this);
    XtRemoveEventHandler(_widget,EnterWindowMask,False,(XtEventHandler)_evh_mouse_in,this);
    XtRemoveEventHandler(_widget,LeaveWindowMask,False,(XtEventHandler)_evh_mouse_out,(WSDxformDev*)this);
    XtRemoveEventHandler(_widget,KeyPressMask | KeyReleaseMask,False,(XtEventHandler)_evh_dummy,(WSDxformDev*)this);
    XtRemoveCallback(_widget,XtNdestroyCallback,_evh_delete2,this);
#if 1 //XUNICODE
    XUFreeInfoWindow(XtDisplay(_widget),XtWindow(_widget));
#endif //UNICODE
    destroy = True;
    XtDestroyWidget(_widget);
    _widget = 0;
  }
  if (_swidget != 0){
#if 1 //USE_XUNICODE
    XUFreeInfoWindow(XtDisplay(_swidget),XtWindow(_swidget));
#endif
 
    XtDestroyWidget(_swidget);
    _swidget = 0;
  }
  if (destroy != False){
    clearChildWidgets();
  }
  setInitialized(False);
  WSGIxwinAppDev()->dispatchEvent();
  if (_sizehints != NULL){
    XFree(_sizehints);
    _sizehints = NULL;
  }
  return WS_NO_ERR;
}

void WSDxwinDev::_float_top_timer_proc(WSCuchar,void* data){
  WSDxwinDev* dev = (WSDxwinDev*)data;
  WSCbool fl = _chk_popup(dev);
  if (fl == False){
    dev->_requested_top = 0;
    return;
  }
  if (dev->getVisible() != False &&
      dev->_swidget != 0 ){
    XWindowChanges wc;
    wc.stack_mode = TopIf;
    if (dev->_top_float != False){
      XConfigureWindow(XtDisplay(dev->_swidget),
                       XtWindow(dev->_swidget),CWStackMode,&wc);
    }
    WSGIappTimer()->addTriggerProc(_float_top_timer_proc,WS500MS,dev);
    dev->_requested_top = 1;
  }else{
    dev->_requested_top = 0;
  }

}
void WSDxwinDev::_clear_widget(){
  _swidget = 0;
  _widget = 0;
  setInitialized(False);
}
long WSDxwinDev::setVisible(WSCbool fl){
WSMFtrace("WSCxwinDev::setVisible _w_h=%d\n",_w_h);
  WSCbool bk = getVisible();
  WSDdev::setVisible(fl);
  if (fl == False){
    if (_swidget != 0){
      if (_no_frame == 0){
        XFlush(XtDisplay(_swidget));
        XUnmapWindow(XtDisplay(_swidget),XtWindow(_swidget));
        XtUnmanageChild(_swidget);
      }else{
         _del_list(this);
        XUnmapWindow(XtDisplay(_swidget),XtWindow(_swidget));
        XFlush(XtDisplay(_swidget));
        XtRemoveCallback(_widget,XtNdestroyCallback,_evh_delete2,this);
        XtDestroyWidget(_swidget);
#if 1 //USE_XUNICODE
        XUFreeInfoWindow(XtDisplay(_swidget),XtWindow(_swidget));
#endif
        clearChildWidgets();
        onUnmap();
        if (_sizehints != NULL){
          XFree(_sizehints);
          _sizehints = NULL;
        }
      }

    }
  }else{
    if (_swidget == 0){
       createWindow();
    }

    if (getPixmapStyle() != WS_DIRECT_WINDOW){
      if (bk == False){
        //delete the pixmap to create in the expose handler...
        destroyPixmap();
      }
    }
    Arg args[10];
    short x,y;    
    WSCushort w,h;    
    getWindowSize(&x,&y,&w,&h);
    if (w == 0){
      w = 1;
    }
    if (h == 0){
      h = 1;
    }
    short x1,y1;    
    WSCushort w1,h1;    
    XtSetArg(args[0],XtNwidth,&w1);
    XtSetArg(args[1],XtNheight,&h1);
    XtSetArg(args[2],XtNx,&x1);
    XtSetArg(args[3],XtNy,&y1);
    XtGetValues(_swidget,args,4);
WSMFtrace("WSDxwinDev::setVisible %d,%d,%d,%d  %d,%d,%d,%d\n",x,y,w,h,x1,y1,w1,h1);
    if (!((x + _diff_x)  == x1 && (y + _diff_y) == y1 && w == w1 && h == h1)){

      XtSetArg(args[0],XtNwidth,w);
      XtSetArg(args[1],XtNheight,h);
      XtSetArg(args[2],XtNx,x);
      XtSetArg(args[3],XtNy,y);
//printf("WSDxwinDev::setVisible value set..\n");
      XtSetValues(_swidget,args,4);
//printf("WSDxwinDev::setVisible here2\n");
      XtSetValues(_widget,args,2);
      XFlush(XtDisplay(_widget));
	}
    XtManageChild(_swidget);
  }
  return WS_NO_ERR;
}

WSDdev* WSDxwinDev::getParentDev(){
  return NULL;
}

void WSDxwinDev::_evh_focus_ch(Widget w,XtPointer ptr,XEvent* ev,WSCbool* fl){
  if (WSGIappDev()->getMode() == WS_MODE_NS_PLUGIN){
    WSGIxwinAppDev()->_dispatchEvent(False,ev);
  }
  WSDxwinDev* dev = (WSDxwinDev*)ptr;
  if (dev->_swidget == NULL){
    return;
  }
  if (ev->type == FocusIn){
    WSCbase* fcl = WSCbase::getFocusInstance();
    if (fcl != NULL){
      WSCbase* cl = dev->getAttachedClient();
      WSCbase* pcl = fcl;
      if (cl != NULL){
        WSCbool fl = False;
        while(1){
          if (pcl == NULL){
            break;
          }
          if (cl == pcl){
            fl = True;
            break;
          }
          pcl = pcl->getParent();
        }
        if (fl != False){
          fcl->onWindowFocusChange(True);
        }else{
          fcl->setFocus(False);
        }
      }else{
        fcl->onWindowFocusChange(True);
      }
    }else{
      dev->onFocusChange();
    }
  }else if (ev->type == FocusOut){
    WSCbase* fcl = WSCbase::getFocusInstance();
    if (fcl != NULL){
      fcl->onWindowFocusChange(False);
    }
  }
}

void WSDxwinDev::_evh_mouse_in(Widget w,XtPointer ptr,XEvent* ev,WSCbool* fl){
  if (WSGIappDev()->getMode() == WS_MODE_NS_PLUGIN){
    WSGIxwinAppDev()->_dispatchEvent(False,ev);
  }
  WSDxwinDev* dev = (WSDxwinDev*)ptr;
  if (dev->_swidget == NULL){
    return;
  }
//printf("dev=0x%x _swidget=0x%x\n",dev,dev->_swidget);
//fflush(stdout);
  long val = WSGIappMouse()->getMouseCursor(dev->_mouse_no);
  if (val != 0){
    XDefineCursor(XtDisplay((Widget)dev->_swidget),XtWindow((Widget)dev->_swidget),val);
  }
  WSDxformDev::_evh_mouse_in(w,(WSDxformDev*)dev,ev,fl);
}

void WSDxwinDev::_evh_delete2(Widget w,XtPointer ptr,XtPointer ){
   WSDxwinDev* dev = (WSDxwinDev*)ptr;
   if (dev->_widget != w){
     return;
   }
   dev->_clear_widget();
   dev->onUnmap();
}

WSClistData WSDxwinDev::_no_frame_list;

void WSDxwinDev::_add_list(WSDxwinDev* dev){
  long num = _no_frame_list.getNum();
  long i;
  WSCbool fl = False;
  for(i=0; i < num; i++){
    WSDxwinDev* item = (WSDxwinDev*)_no_frame_list.getData(i);
    if (item == dev){
      fl = True;
      break;
    }
  }
  if (fl == False){
    _no_frame_list.add((void*)dev);
  }
}

void WSDxwinDev::_del_list(WSDxwinDev* dev){
  _no_frame_list.del((void*)dev);
}

WSCbool WSDxwinDev::_chk_popup(WSDxwinDev* dev){
    //force popup at first time...
    if (dev->_no_frame_first_time != 0){
      dev->_no_frame_first_time = 0;
      return True;
    }
    long i;
    for(i=0; i<_no_frame_list.getNum(); i++){
      WSDxwinDev* item = (WSDxwinDev*)_no_frame_list.getData(i);
      if (item != dev ){
        if ( item->getVisible() == False){
           _del_list(item);
           i--;
        }else{
          long dx,dy;
          WSCulong dw,dh;
          if (WSGFandArea(item->_w_x,item->_w_y,item->_w_w,item->_w_h,
                          dev->_w_x,dev->_w_y,dev->_w_w,dev->_w_h,
                          &dx,&dy,&dw,&dh) == WS_NO_ERR){
            return False;
          }

        }
      } 
    }
    return True;
}

void WSDxwinDev::_popup_window(WSDxwinDev* dev){
//printf("WSDxwinDev::_popup_window \n");
    _add_list(dev);
    WSCbool fl = _chk_popup(dev);
    if (fl == False){
      return;
    }

//    XWindowChanges wc;
//    wc.stack_mode = TopIf;
//    XConfigureWindow(XtDisplay(dev->_swidget),XtWindow(dev->_swidget),CWStackMode,&wc);
    if (dev->_requested_top == 0){
      _float_top_timer_proc(0,dev);
    }
}

void WSDxwinDev::_evh_resize(Widget w,XtPointer ptr,XEvent* ev,WSCbool* ){
  if (WSGIappDev()->getMode() == WS_MODE_NS_PLUGIN){
    WSGIxwinAppDev()->_dispatchEvent(False,ev);
  }
  WSDxwinDev* dev = (WSDxwinDev*)ptr;
  if (ev->type == ReparentNotify){
    if (dev->getVisible() == False){
      return;
    }
    short x,y;
    WSCushort nw,nh;
    Arg args[4];
    XtSetArg(args[0],XtNy,&y);
    XtSetArg(args[1],XtNx,&x);
    XtSetArg(args[2],XtNwidth,&nw);
    XtSetArg(args[3],XtNheight,&nh);
    XtGetValues(dev->_swidget,args,4);
    dev->_diff_x = x - dev->_w_x; 
    if (dev->_diff_x < 0){
      dev->_diff_x = 0;
    }else if (dev->_diff_x > 40){
      dev->_diff_x = 0;
    }
    dev->_diff_y = y - dev->_w_y; 
    if (dev->_diff_y < 0){
      dev->_diff_y = 0;
    }else if (dev->_diff_y > 40){
      dev->_diff_y = 0;
    }
    if (wm_protocols == 0){
      wm_protocols = XInternAtom(XtDisplay(w),"WM_PROTOCOLS",False);
    }
    if (wm_delete == 0){
      wm_delete = XInternAtom(XtDisplay(w),"WM_DELETE_WINDOW",False);
    }
    if (dev->_swidget != NULL){
      XSetWMProtocols(XtDisplay(dev->_swidget),
                      XtWindow(dev->_swidget),&wm_delete,1);
    }
    
//printf("WSDxwinDev::_evh_resize here! %d\n",dev->_title_bar);
    if (dev->_title_bar == WS_ONLY_TITLE && dev->_sizehints == NULL){
//printf("WSDxwinDev::_evh_resize here\n");
      dev->_sizehints = XAllocSizeHints();
//      dev->_sizehints->flags = USPosition | USSize | PMinSize | PMaxSize ;
      dev->_sizehints->flags = USSize | PMinSize | PMaxSize ;
      dev->_sizehints->min_width = nw;
      dev->_sizehints->max_width = nw;
      dev->_sizehints->base_width = nw;
      dev->_sizehints->min_height = nh;
      dev->_sizehints->max_height = nh;
      dev->_sizehints->base_height = nh;
      XSetWMProperties(XtDisplay(w), XtWindow(w), NULL, NULL,
                 NULL, 0, dev->_sizehints, NULL, NULL);
    }

    WSCrect area;
    area.setRect(x - dev->_diff_x,y - dev->_diff_y, nw,nh);
WSMFtrace("WSDxwinDev::_evh_resize %d,%d,%d,%d\n",area.x,area.y,area.width,area.height);
    dev->onResize(&area);
  }
 
  if (dev->_swidget == NULL){
    return;
  }

  if (dev->_title_bar_style == 0 && dev->_no_frame == 1 &&
    ev->type == MapNotify && dev->_top_float == False){
    XSetInputFocus(XtDisplay((Widget)dev->_swidget),XtWindow((Widget)dev->_swidget),
                               RevertToParent,CurrentTime);
  }


  if (dev->_title_bar_style == 0 && dev->_no_frame == 1 &&
      ev->type == ConfigureNotify){
    _popup_window(dev);
  }else if (dev->_top_float == 1 && dev->_requested_top == 0){
    _popup_window(dev);
  }
  if (ev->type == ConfigureNotify &&
      XtWindow(dev->_swidget) == ev->xconfigure.window){
    int dustx,dusty;
    WSCuint vw,vh,vborder,vdepth;
    Window root;
    XGetGeometry( XtDisplay((Widget)dev->_swidget),
                  XtWindow((Widget)dev->_swidget),&root,&dustx,&dusty,
                  &vw,&vh,&vborder,&vdepth);
    if (ev->xconfigure.width != (long)vw ||
        ev->xconfigure.height != (long)vh ){
      return;
    }

    short x,y;
//    WSCushort w,h;
    Arg args[4];
    XtSetArg(args[0],XtNy,&y);
    XtSetArg(args[1],XtNx,&x);
    XtGetValues(dev->_swidget,args,2);
    WSCrect area;

    area.setRect(x - dev->_diff_x,
                 y - dev->_diff_y,
                 ev->xconfigure.width,
                 ev->xconfigure.height);
WSMFtrace("WSDxwinDev::_evh_resize2 %d,%d,%d,%d\n",area.x,area.y,area.width,area.height);
    dev->onResize(&area);
    WSGIxwinAppDev()->setXEvent(NULL);

  }
}

void WSDxwinDev::_evh_expose(Widget w,XtPointer ptr,XEvent* ev,WSCbool* fl){
  if (WSGIappDev()->getMode() == WS_MODE_NS_PLUGIN){
    WSGIxwinAppDev()->_dispatchEvent(False,ev);
  }
  WSDxwinDev* dev = (WSDxwinDev*)ptr;
  if (wm_protocols == 0){
    wm_protocols = XInternAtom(XtDisplay(w),"WM_PROTOCOLS",False);
  }
  if (wm_delete == 0){
    wm_delete = XInternAtom(XtDisplay(w),"WM_DELETE_WINDOW",False);
  }
  if (dev->_swidget == NULL){
    return;
  }
  if (dev->_swidget != NULL){
    XSetWMProtocols(XtDisplay(dev->_swidget),
                    XtWindow(dev->_swidget),&wm_delete,1);
  }
  if (dev->_title_bar_style == 0 && dev->_no_frame == 1 ){
    if (dev->_top_float != False){
//printf("WSDxwinDev::_evh_expose _popup_win..\n");
      _popup_window(dev);
    }
  }
  WSDxformDev::_evh_expose(w,(WSDxformDev*)dev,ev,fl);
}

Widget WSDxwinDev::getShell(){
  return _swidget;
}

void WSDxwinDev::_evh_client_message(Widget w,XtPointer ptr,XEvent* ev,WSCbool* fl){
  if (WSGIappDev()->getMode() == WS_MODE_NS_PLUGIN){
    WSGIxwinAppDev()->_dispatchEvent(False,ev);
  }
//printf("WSDxwinDev::_evh_client_message !! XXXZZ\n");
  WSDxwinDev* dev = (WSDxwinDev*)ptr;
  if (ev->type == ClientMessage){
    WSCbase* client = dev->getAttachedClient();
	if (client != NULL){
	  client->setVisible(False);
	}
  }
}

long WSDxwinDev::getValue(long kind,void* val){
  switch(kind){
    case WSDEV_WINDOW_STATE:
      if (getVisible() == False){
        return WS_WINDOW_NORMAL;
      }
      if (_swidget == NULL){
        return WS_ERR;
      }
      XWindowAttributes att;
      Display* disp =  XtDisplay(_swidget);
      Window   target =  XtWindow(_swidget);
      XGetWindowAttributes(disp, target, &att);
      if (att.map_state == IsUnmapped){
        return WS_WINDOW_MINIMIZE;
      }
      return WS_WINDOW_NORMAL;
  }
  return WSDwindowDev::getValue(kind,val);
}
