]> git.saurik.com Git - wxWidgets.git/commitdiff
Implemented two-window approach for wxX11.
authorRobert Roebling <robert@roebling.de>
Sun, 24 Mar 2002 22:17:53 +0000 (22:17 +0000)
committerRobert Roebling <robert@roebling.de>
Sun, 24 Mar 2002 22:17:53 +0000 (22:17 +0000)
  Implemented wxSTAY_ON_TOP the way Qt does it.
  Added group window support.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@14764 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/univ/window.h
include/wx/x11/private.h
include/wx/x11/reparent.h
include/wx/x11/window.h
src/univ/winuniv.cpp
src/x11/app.cpp
src/x11/dcclient.cpp
src/x11/popupwin.cpp
src/x11/reparent.cpp
src/x11/toplevel.cpp
src/x11/window.cpp

index 02b48e85ebd95b371ad531543714db11d2166e2d..fa1aaec62a59f6da9bd561307987720b9392041d 100644 (file)
@@ -51,6 +51,12 @@ enum
     wxCONTROL_DIRTY      = 0x80000000
 };
 
     wxCONTROL_DIRTY      = 0x80000000
 };
 
+#ifdef __WXX11__
+#define wxUSE_TWO_WINDOWS 1
+#else
+#define wxUSE_TWO_WINDOWS 0
+#endif
+
 // ----------------------------------------------------------------------------
 // wxWindow
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // wxWindow
 // ----------------------------------------------------------------------------
index ed33270f6cd6f65c0382b1cbacc27fa844f86628..bb6d9be7f6c8dea7f63a7daa37c9eb05e869a542 100644 (file)
@@ -34,6 +34,10 @@ extern void wxDeleteWindowFromTable(Window w);
 extern wxWindow *wxGetWindowFromTable(Window w);
 extern bool wxAddWindowToTable(Window w, wxWindow *win);
 
 extern wxWindow *wxGetWindowFromTable(Window w);
 extern bool wxAddWindowToTable(Window w, wxWindow *win);
 
+extern void wxDeleteClientWindowFromTable(Window w);
+extern wxWindow *wxGetClientWindowFromTable(Window w);
+extern bool wxAddClientWindowToTable(Window w, wxWindow *win);
+
 // ----------------------------------------------------------------------------
 // TranslateXXXEvent() functions - translate X event to wxWindow one
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // TranslateXXXEvent() functions - translate X event to wxWindow one
 // ----------------------------------------------------------------------------
index 8170084a19c59f6fbd54ca09d3a251b7bd4472f9..815024d40bdf4e6cebf6f0040b5eaf4094310d75 100644 (file)
@@ -63,8 +63,8 @@ class wxAdoptedWindow: public wxWindow
     wxAdoptedWindow(WXWindow window);
     ~wxAdoptedWindow();
 
     wxAdoptedWindow(WXWindow window);
     ~wxAdoptedWindow();
 
-    void SetHandle(WXWindow window) { m_mainWidget = window; }
-    WXWindow GetHandle() const { return GetXWindow(); }
+    void SetHandle(WXWindow window) { m_mainWindow = window; }
+    WXWindow GetHandle() const { return GetMainWindow(); }
 };
 
 #endif
 };
 
 #endif
index 90863adfca4b8ae650db376f169b399276195cab..feace83629c6736762616ab635cd0c45b61109f1 100644 (file)
@@ -103,12 +103,11 @@ public:
     // accessors
     // ---------
     
     // accessors
     // ---------
     
-    // Get main widget for this window, e.g. a text widget
+    // Get main X11 window
     virtual WXWindow GetMainWindow() const;
     
     virtual WXWindow GetMainWindow() const;
     
-    // Get the underlying X window and display
-    WXWindow GetXWindow() const;
-    WXDisplay *GetXDisplay() const;
+    // Get X11 window representing the client area
+    virtual WXWindow GetClientWindow() const;
     
     void SetLastClick(int button, long timestamp)
         { m_lastButton = button; m_lastTS = timestamp; }
     
     void SetLastClick(int button, long timestamp)
         { m_lastButton = button; m_lastTS = timestamp; }
@@ -123,6 +122,9 @@ public:
     // Generates paint events from m_updateRegion
     void SendPaintEvents();
     
     // Generates paint events from m_updateRegion
     void SendPaintEvents();
     
+    // Generates paint events from flag
+    void SendNcPaintEvents();
+    
     // Generates erase events from m_clearRegion
     void SendEraseEvents();
     
     // Generates erase events from m_clearRegion
     void SendEraseEvents();
     
@@ -132,6 +134,14 @@ public:
     // Return clear region
     wxRegion &GetClearRegion() { return m_clearRegion; }
     
     // Return clear region
     wxRegion &GetClearRegion() { return m_clearRegion; }
     
+    void NeedUpdateNcAreaInIdle( bool update = TRUE ) { m_updateNcArea = update; }
+    
+    // Inserting into main window instead of client
+    // window. This is mostly for a wxWindow's own
+    // scrollbars.
+    void SetInsertIntoMain( bool insert = TRUE ) { m_insertIntoMain = insert; }
+    bool GetInsertIntoMain() { return m_insertIntoMain; }
+    
     // sets the fore/background colour for the given widget
     static void DoChangeForegroundColour(WXWindow widget, wxColour& foregroundColour);
     static void DoChangeBackgroundColour(WXWindow widget, wxColour& backgroundColour, bool changeArmColour = FALSE);
     // sets the fore/background colour for the given widget
     static void DoChangeForegroundColour(WXWindow widget, wxColour& foregroundColour);
     static void DoChangeBackgroundColour(WXWindow widget, wxColour& backgroundColour, bool changeArmColour = FALSE);
@@ -148,10 +158,6 @@ public:
     // For compatibility across platforms (not in event table)
     void OnIdle(wxIdleEvent& WXUNUSED(event)) {}
     
     // For compatibility across platforms (not in event table)
     void OnIdle(wxIdleEvent& WXUNUSED(event)) {}
     
-    // Go up to a toplevel window and query which window has the focus.
-    // May return NULL.
-    wxWindow *GetFocusWidget();
-    
 protected:
     // Responds to colour changes: passes event on to children.
     void OnSysColourChanged(wxSysColourChangedEvent& event);
 protected:
     // Responds to colour changes: passes event on to children.
     void OnSysColourChanged(wxSysColourChangedEvent& event);
@@ -161,10 +167,14 @@ protected:
     int    m_lastButton;     // last pressed button
     
 protected:
     int    m_lastButton;     // last pressed button
     
 protected:
-    WXWindow              m_mainWidget;
+    WXWindow              m_mainWindow;
+    WXWindow              m_clientWindow;
+    bool                  m_insertIntoMain;
+    
+    bool                  m_winCaptured;
     wxRegion              m_clearRegion;
     bool                  m_clipPaintRegion;
     wxRegion              m_clearRegion;
     bool                  m_clipPaintRegion;
-    bool                  m_winCaptured;  // ????
+    bool                  m_updateNcArea;
     bool                  m_needsInputFocus; // Input focus set in OnIdle
 
     // implement the base class pure virtuals
     bool                  m_needsInputFocus; // Input focus set in OnIdle
 
     // implement the base class pure virtuals
index 83a0c68761afccef3477e4b5569c084c1c57fd7d..be8a2ba4e3a23759b05a3eb0ac38d1b886558de7 100644 (file)
@@ -132,9 +132,15 @@ bool wxWindow::Create(wxWindow *parent,
     // if we should always have the scrollbar, do show it
     if ( GetWindowStyle() & wxALWAYS_SHOW_SB )
     {
     // if we should always have the scrollbar, do show it
     if ( GetWindowStyle() & wxALWAYS_SHOW_SB )
     {
+#if wxUSE_TWO_WINDOWS
+        SetInsertIntoMain( TRUE );
+#endif
         m_scrollbarVert = new wxScrollBar(this, -1,
                                           wxDefaultPosition, wxDefaultSize,
                                           wxSB_VERTICAL);
         m_scrollbarVert = new wxScrollBar(this, -1,
                                           wxDefaultPosition, wxDefaultSize,
                                           wxSB_VERTICAL);
+#if wxUSE_TWO_WINDOWS
+        SetInsertIntoMain( FALSE );
+#endif
 
         // and position it
         PositionScrollbars();
 
         // and position it
         PositionScrollbars();
@@ -456,7 +462,7 @@ void wxWindow::OnSize(wxSizeEvent& event)
         PositionScrollbars();
     }
     
         PositionScrollbars();
     }
     
-#ifndef __WXMSW__
+#if 0   // ndef __WXMSW__
     // Refresh the area (strip) previously occupied by the border
     
     if (HasFlag( wxNO_FULL_REPAINT_ON_RESIZE ) && IsShown())
     // Refresh the area (strip) previously occupied by the border
     
     if (HasFlag( wxNO_FULL_REPAINT_ON_RESIZE ) && IsShown())
@@ -581,8 +587,11 @@ wxPoint wxWindow::GetClientAreaOrigin() const
 {
     wxPoint pt = wxWindowBase::GetClientAreaOrigin();
 
 {
     wxPoint pt = wxWindowBase::GetClientAreaOrigin();
 
+#if wxUSE_TWO_WINDOWS
+#else
     if ( m_renderer )
         pt += m_renderer->GetBorderDimensions(GetBorder()).GetPosition();
     if ( m_renderer )
         pt += m_renderer->GetBorderDimensions(GetBorder()).GetPosition();
+#endif
 
     return pt;
 }
 
     return pt;
 }
@@ -771,10 +780,16 @@ void wxWindow::SetScrollbar(int orient,
         if ( !scrollbar )
         {
             // create it
         if ( !scrollbar )
         {
             // create it
+#if wxUSE_TWO_WINDOWS
+            SetInsertIntoMain( TRUE );
+#endif
             scrollbar = new wxScrollBar(this, -1,
                                         wxDefaultPosition, wxDefaultSize,
                                         orient & wxVERTICAL ? wxSB_VERTICAL
                                                             : wxSB_HORIZONTAL);
             scrollbar = new wxScrollBar(this, -1,
                                         wxDefaultPosition, wxDefaultSize,
                                         orient & wxVERTICAL ? wxSB_VERTICAL
                                                             : wxSB_HORIZONTAL);
+#if wxUSE_TWO_WINDOWS
+            SetInsertIntoMain( FALSE );
+#endif
             if ( orient & wxVERTICAL )
                 m_scrollbarVert = scrollbar;
             else
             if ( orient & wxVERTICAL )
                 m_scrollbarVert = scrollbar;
             else
index 8d9e58933ba0acd13636d36ef6358d798d492851..e1a0d8027ecc0eb7dabd579b59e1b6a4267ebc6b 100644 (file)
@@ -49,6 +49,7 @@
 extern wxList wxPendingDelete;
 
 wxHashTable *wxWidgetHashTable = NULL;
 extern wxList wxPendingDelete;
 
 wxHashTable *wxWidgetHashTable = NULL;
+wxHashTable *wxClientWidgetHashTable = NULL;
 
 wxApp *wxTheApp = NULL;
 
 
 wxApp *wxTheApp = NULL;
 
@@ -119,6 +120,7 @@ bool wxApp::Initialize()
 #endif
 
     wxWidgetHashTable = new wxHashTable(wxKEY_INTEGER);
 #endif
 
     wxWidgetHashTable = new wxHashTable(wxKEY_INTEGER);
+    wxClientWidgetHashTable = new wxHashTable(wxKEY_INTEGER);
 
     wxModule::RegisterModules();
     if (!wxModule::InitializeModules()) return FALSE;
 
     wxModule::RegisterModules();
     if (!wxModule::InitializeModules()) return FALSE;
@@ -134,6 +136,8 @@ void wxApp::CleanUp()
 
     delete wxWidgetHashTable;
     wxWidgetHashTable = NULL;
 
     delete wxWidgetHashTable;
     wxWidgetHashTable = NULL;
+    delete wxClientWidgetHashTable;
+    wxClientWidgetHashTable = NULL;
 
     wxModule::CleanUpModules();
 
 
     wxModule::CleanUpModules();
 
@@ -466,10 +470,16 @@ bool wxApp::ProcessXEvent(WXEvent* _event)
     // has been destroyed, assume a 1:1 match between
     // Window and wxWindow, so if it's not in the table,
     // it must have been destroyed.
     // has been destroyed, assume a 1:1 match between
     // Window and wxWindow, so if it's not in the table,
     // it must have been destroyed.
-
+    
     win = wxGetWindowFromTable(window);
     if (!win)
     win = wxGetWindowFromTable(window);
     if (!win)
-        return FALSE;
+    {
+#if wxUSE_TWO_WINDOWS
+        win = wxGetClientWindowFromTable(window);
+        if (!win)
+#endif
+            return FALSE;
+    }
 
 #ifdef __WXDEBUG__
     wxString windowClass = win->GetClassInfo()->GetClassName();
 
 #ifdef __WXDEBUG__
     wxString windowClass = win->GetClassInfo()->GetClassName();
@@ -479,30 +489,49 @@ bool wxApp::ProcessXEvent(WXEvent* _event)
     {
         case Expose:
         {
     {
         case Expose:
         {
-            //wxLogDebug("Expose: %s", windowClass.c_str());
-            win->GetUpdateRegion().Union( XExposeEventGetX(event), XExposeEventGetY(event),
-                                          XExposeEventGetWidth(event), XExposeEventGetHeight(event));
+#if wxUSE_TWO_WINDOWS
+            if (event->xexpose.window != (Window)win->GetClientWindow())
+            {
+                XEvent tmp_event;
+                wxExposeInfo info;
+                info.window = event->xexpose.window;
+                info.found_non_matching = FALSE;
+                while (XCheckIfEvent( wxGlobalDisplay(), &tmp_event, expose_predicate, (XPointer) &info ))
+                {
+                    // Don't worry about optimizing redrawing the border etc.
+                }
+                win->NeedUpdateNcAreaInIdle();
+            }
+            else
+#endif
+            {
+                win->GetUpdateRegion().Union( XExposeEventGetX(event), XExposeEventGetY(event),
+                                              XExposeEventGetWidth(event), XExposeEventGetHeight(event));
                                               
                                               
-            win->GetClearRegion().Union( XExposeEventGetX(event), XExposeEventGetY(event),
+                win->GetClearRegion().Union( XExposeEventGetX(event), XExposeEventGetY(event),
                                          XExposeEventGetWidth(event), XExposeEventGetHeight(event));
 
 #if !wxUSE_NANOX
                                          XExposeEventGetWidth(event), XExposeEventGetHeight(event));
 
 #if !wxUSE_NANOX
-            XEvent tmp_event;
-            wxExposeInfo info;
-            info.window = event->xexpose.window;
-            info.found_non_matching = FALSE;
-            while (XCheckIfEvent( wxGlobalDisplay(), &tmp_event, expose_predicate, (XPointer) &info ))
-            {
-                win->GetUpdateRegion().Union( tmp_event.xexpose.x, tmp_event.xexpose.y,
-                                              tmp_event.xexpose.width, tmp_event.xexpose.height );
+                XEvent tmp_event;
+                wxExposeInfo info;
+                info.window = event->xexpose.window;
+                info.found_non_matching = FALSE;
+                while (XCheckIfEvent( wxGlobalDisplay(), &tmp_event, expose_predicate, (XPointer) &info ))
+                {
+                    win->GetUpdateRegion().Union( tmp_event.xexpose.x, tmp_event.xexpose.y,
+                                                  tmp_event.xexpose.width, tmp_event.xexpose.height );
                                               
                                               
-                win->GetClearRegion().Union( tmp_event.xexpose.x, tmp_event.xexpose.y,
-                                             tmp_event.xexpose.width, tmp_event.xexpose.height );
-            }
+                    win->GetClearRegion().Union( tmp_event.xexpose.x, tmp_event.xexpose.y,
+                                                 tmp_event.xexpose.width, tmp_event.xexpose.height );
+                }
 #endif
 #endif
+                if (win->GetMainWindow() == win->GetClientWindow())
+                    win->NeedUpdateNcAreaInIdle();
 
 
-            // Only erase background, paint in idle time.
-            win->SendEraseEvents();
+                // Only erase background, paint in idle time.
+                win->SendEraseEvents();
+                //win->Update();
+            }
 
             return TRUE;
         }
 
             return TRUE;
         }
@@ -580,7 +609,6 @@ bool wxApp::ProcessXEvent(WXEvent* _event)
             if (event->update.utype == GR_UPDATE_SIZE)
 #endif
             {
             if (event->update.utype == GR_UPDATE_SIZE)
 #endif
             {
-                //wxLogDebug("ConfigureNotify: %s", windowClass.c_str());
                 if (win->IsTopLevel() && win->IsShown())
                 {
                     wxTopLevelWindowX11 *tlw = (wxTopLevelWindowX11 *) win;
                 if (win->IsTopLevel() && win->IsShown())
                 {
                     wxTopLevelWindowX11 *tlw = (wxTopLevelWindowX11 *) win;
index c6c808c37601f1fae95b748e78ecbf2656863f4f..23629d550058d5ac524692e34e95159a0e3ad834 100644 (file)
@@ -2030,53 +2030,24 @@ int wxWindowDC::GetDepth() const
     return -1;
 }
 
     return -1;
 }
 
-// ----------------------------------------------------------------------------
-// wxPaintDC
-// ----------------------------------------------------------------------------
-
-IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxClientDC)
-
-wxPaintDC::wxPaintDC(wxWindow* win)
-  : wxClientDC(win)
-{
-#if USE_PAINT_REGION
-    if (!win->GetClipPaintRegion())
-        return;
-
-    m_paintClippingRegion = win->GetUpdateRegion();
-    Region region = (Region) m_paintClippingRegion.GetX11Region();
-    if (region)
-    {
-        m_paintClippingRegion = win->GetUpdateRegion();
-        Region region2 = (Region) m_paintClippingRegion.GetX11Region();
-        if (region2)
-        {
-            m_currentClippingRegion.Union( m_paintClippingRegion );
-
-            XSetRegion( (Display*) m_display, (GC) m_penGC, region2 );
-            XSetRegion( (Display*) m_display, (GC) m_brushGC, region2 );
-            XSetRegion( (Display*) m_display, (GC) m_textGC, region2 );
-            XSetRegion( (Display*) m_display, (GC) m_bgGC, region2 );
-        }
-    }
-#endif // USE_PAINT_REGION
-}
-
 //-----------------------------------------------------------------------------
 // wxClientDC
 //-----------------------------------------------------------------------------
 
 IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC)
 
 //-----------------------------------------------------------------------------
 // wxClientDC
 //-----------------------------------------------------------------------------
 
 IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC)
 
-wxClientDC::wxClientDC( wxWindow *win )
-          : wxWindowDC( win )
+wxClientDC::wxClientDC( wxWindow *window )
+          : wxWindowDC( window )
 {
 {
-    wxCHECK_RET( win, _T("NULL window in wxClientDC::wxClientDC") );
+    wxCHECK_RET( window, _T("NULL window in wxClientDC::wxClientDC") );
     
     
-#ifdef __WXUNIVERSAL__
-    wxPoint ptOrigin = win->GetClientAreaOrigin();
+    m_window = (WXWindow*) window->GetClientWindow();
+    
+#if wxUSE_TWO_WINDOWS
+#else
+    wxPoint ptOrigin = window->GetClientAreaOrigin();
     SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
     SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
-    wxSize size = win->GetClientSize();
+    wxSize size = window->GetClientSize();
     SetClippingRegion(wxPoint(0, 0), size);
 #endif // __WXUNIVERSAL__
 }
     SetClippingRegion(wxPoint(0, 0), size);
 #endif // __WXUNIVERSAL__
 }
@@ -2088,6 +2059,33 @@ void wxClientDC::DoGetSize(int *width, int *height) const
     m_owner->GetClientSize( width, height );
 }
 
     m_owner->GetClientSize( width, height );
 }
 
+// ----------------------------------------------------------------------------
+// wxPaintDC
+// ----------------------------------------------------------------------------
+
+IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxClientDC)
+
+wxPaintDC::wxPaintDC(wxWindow* window)
+  : wxClientDC(window)
+{
+#if USE_PAINT_REGION
+    if (!window->GetClipPaintRegion())
+        return;
+
+    m_paintClippingRegion = window->GetUpdateRegion();
+    Region region = (Region) m_paintClippingRegion.GetX11Region();
+    if (region)
+    {
+            m_currentClippingRegion.Union( m_paintClippingRegion );
+
+            XSetRegion( (Display*) m_display, (GC) m_penGC, region );
+            XSetRegion( (Display*) m_display, (GC) m_brushGC, region );
+            XSetRegion( (Display*) m_display, (GC) m_textGC, region );
+            XSetRegion( (Display*) m_display, (GC) m_bgGC, region );
+    }
+#endif // USE_PAINT_REGION
+}
+
 // ----------------------------------------------------------------------------
 // wxDCModule
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // wxDCModule
 // ----------------------------------------------------------------------------
index 818b86fc64f0c8ca32fb6c79dd11f31552fa360a..9161a1e64198b646ce4692fb4251ae371a968877 100644 (file)
@@ -78,7 +78,8 @@ bool wxPopupWindow::Create( wxWindow *parent, int style )
         KeymapStateMask | FocusChangeMask | ColormapChangeMask | StructureNotifyMask |
         PropertyChangeMask );
 
         KeymapStateMask | FocusChangeMask | ColormapChangeMask | StructureNotifyMask |
         PropertyChangeMask );
 
-    m_mainWidget = (WXWindow) xwindow;
+    m_mainWindow = (WXWindow) xwindow;
+    m_clientWindow = (WXWindow) xwindow;
     wxAddWindowToTable( xwindow, (wxWindow*) this );
 
     // Set background to None which will prevent X11 from clearing the
     wxAddWindowToTable( xwindow, (wxWindow*) this );
 
     // Set background to None which will prevent X11 from clearing the
index 7a6482426582180d25f4232aeddb9478f490156e..bbeedaea5dbeb4fb68b4d0c36efacfe59d091c1f 100644 (file)
@@ -94,7 +94,7 @@ wxAdoptedWindow::wxAdoptedWindow()
 
 wxAdoptedWindow::wxAdoptedWindow(WXWindow window)
 {
 
 wxAdoptedWindow::wxAdoptedWindow(WXWindow window)
 {
-    m_mainWidget = window;
+    m_mainWindow = window;
 }
 
 wxAdoptedWindow::~wxAdoptedWindow()
 }
 
 wxAdoptedWindow::~wxAdoptedWindow()
@@ -131,15 +131,15 @@ bool wxReparenter::Reparent(wxWindow* newParent, wxAdoptedWindow* toReparent)
     int parentOffset = 0;
 
     old = XSetErrorHandler(ErrorHandler);
     int parentOffset = 0;
 
     old = XSetErrorHandler(ErrorHandler);
-    XReparentWindow((Display*) newParent->GetXDisplay(),
-                    (Window) toReparent->GetXWindow(),
-                    (Window) newParent->GetXWindow(),
-                    0, 0);
-
-    if (!XQueryTree((Display*) newParent->GetXDisplay(),
-                    (Window) toReparent->GetXWindow(),
-                    &returnroot, &returnparent,
-                    &children, &numchildren) || Xerror)
+    XReparentWindow( wxGlobalDisplay(),
+                     (Window) toReparent->GetMainWindow(),
+                     (Window) newParent->GetMainWindow(),
+                     0, 0);
+
+    if (!XQueryTree( wxGlobalDisplay(),
+                     (Window) toReparent->GetMainWindow(),
+                     &returnroot, &returnparent,
+                     &children, &numchildren) || Xerror)
     {
         XSetErrorHandler(old);
         return TRUE;
     {
         XSetErrorHandler(old);
         return TRUE;
@@ -160,14 +160,14 @@ bool wxReparenter::Reparent(wxWindow* newParent, wxAdoptedWindow* toReparent)
          */
         for (each=0; each<numchildren; each++)
         {
          */
         for (each=0; each<numchildren; each++)
         {
-            XGetWindowAttributes((Display*) newParent->GetXDisplay(),
-                                 children[each], &xwa);
+            XGetWindowAttributes( wxGlobalDisplay(),
+                                  children[each], &xwa);
             fprintf(stderr,
               "Reparenting child at offset %d and position %d, %d.\n",
                parentOffset, parentOffset+xwa.x, parentOffset+xwa.y);
             fprintf(stderr,
               "Reparenting child at offset %d and position %d, %d.\n",
                parentOffset, parentOffset+xwa.x, parentOffset+xwa.y);
-            XReparentWindow((Display*) newParent->GetXDisplay(),
-                            children[each], (Window) newParent->GetXWindow(),
-              xwa.x, xwa.y);
+            XReparentWindow( wxGlobalDisplay(),
+                             children[each], (Window) newParent->GetMainWindow(),
+                             xwa.x, xwa.y);
         }
     }
 
         }
     }
 
@@ -187,7 +187,7 @@ bool wxReparenter::WaitAndReparent(wxWindow* newParent, wxAdoptedWindow* toRepar
     sm_exactMatch = exactMatch;
     sm_name = windowName;
     
     sm_exactMatch = exactMatch;
     sm_name = windowName;
     
-    Display* display = (Display*) newParent->GetXDisplay() ;
+    Display* display = wxGlobalDisplay();
     XSelectInput(display,
         RootWindowOfScreen(DefaultScreenOfDisplay(display)),
         SubstructureNotifyMask);
     XSelectInput(display,
         RootWindowOfScreen(DefaultScreenOfDisplay(display)),
         SubstructureNotifyMask);
index 1e84bc6b1c3286d52d3b30594d5c9d353892a642..56ffc9d7d40062cde0f86ad1fb71a9e8b8b3c86d 100644 (file)
@@ -123,12 +123,18 @@ bool wxTopLevelWindowX11::Create(wxWindow *parent,
     xattributes.background_pixel = m_backgroundColour.GetPixel();
     xattributes.border_pixel = BlackPixel( xdisplay, xscreen );
 
     xattributes.background_pixel = m_backgroundColour.GetPixel();
     xattributes.border_pixel = BlackPixel( xdisplay, xscreen );
 
+    if (HasFlag( wxNO_BORDER ))
+    {
+        xattributes_mask |= CWOverrideRedirect;
+        xattributes.override_redirect = True;
+    }
+    
     if (HasFlag( wxNO_FULL_REPAINT_ON_RESIZE ))
     {
         xattributes_mask |= CWBitGravity;
         xattributes.bit_gravity = StaticGravity;
     }
     if (HasFlag( wxNO_FULL_REPAINT_ON_RESIZE ))
     {
         xattributes_mask |= CWBitGravity;
         xattributes.bit_gravity = StaticGravity;
     }
-
+    
     xattributes_mask |= CWEventMask;
     xattributes.event_mask = 
         ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
     xattributes_mask |= CWEventMask;
     xattributes.event_mask = 
         ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
@@ -147,7 +153,9 @@ bool wxTopLevelWindowX11::Create(wxWindow *parent,
                                     0, 0, InputOutput, xvisual, backColor, foreColor);
 #endif
 
                                     0, 0, InputOutput, xvisual, backColor, foreColor);
 #endif
 
-    m_mainWidget = (WXWindow) xwindow;
+    m_mainWindow = (WXWindow) xwindow;
+    m_clientWindow = (WXWindow) xwindow;
+    wxAddWindowToTable( xwindow, (wxWindow*) this );
 
 #if wxUSE_NANOX
     XSelectInput( xdisplay, xwindow,
 
 #if wxUSE_NANOX
     XSelectInput( xdisplay, xwindow,
@@ -168,20 +176,26 @@ bool wxTopLevelWindowX11::Create(wxWindow *parent,
                   PropertyChangeMask
                   );
 #endif
                   PropertyChangeMask
                   );
 #endif
-    
-    wxAddWindowToTable( xwindow, (wxWindow*) this );
 
     // Set background to None which will prevent X11 from clearing the
     // background completely.
     XSetWindowBackgroundPixmap( xdisplay, xwindow, None );
 
 #if !wxUSE_NANOX
 
     // Set background to None which will prevent X11 from clearing the
     // background completely.
     XSetWindowBackgroundPixmap( xdisplay, xwindow, None );
 
 #if !wxUSE_NANOX
-    if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG)
+    if (HasFlag( wxSTAY_ON_TOP ))
     {
     {
-        if (GetParent() && GetParent()->GetMainWindow())
-        {
-             Window xparentwindow = (Window) GetParent()->GetMainWindow();
-             XSetTransientForHint( xdisplay, xwindow, xparentwindow );
+        Window xroot = RootWindow( xdisplay, xscreen );
+        XSetTransientForHint( xdisplay, xwindow, xroot );
+    }
+    else
+    {
+       if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG)
+       {
+            if (GetParent() && GetParent()->GetMainWindow())
+            {
+                Window xparentwindow = (Window) GetParent()->GetMainWindow();
+                XSetTransientForHint( xdisplay, xwindow, xparentwindow );
+            }
         }
     }
 
         }
     }
 
@@ -193,7 +207,12 @@ bool wxTopLevelWindowX11::Create(wxWindow *parent,
     XSetWMNormalHints( xdisplay, xwindow, &size_hints);
     
     XWMHints wm_hints;
     XSetWMNormalHints( xdisplay, xwindow, &size_hints);
     
     XWMHints wm_hints;
-    wm_hints.flags = InputHint | StateHint /* | WindowGroupHint */;
+    wm_hints.flags = InputHint | StateHint;
+    if (GetParent())
+    {  
+        wm_hints.flags |= WindowGroupHint;
+        wm_hints.window_group = (Window) GetParent()->GetMainWindow();
+    }
     wm_hints.input = True;
     wm_hints.initial_state = NormalState;
     XSetWMHints( xdisplay, xwindow, &wm_hints);
     wm_hints.input = True;
     wm_hints.initial_state = NormalState;
     XSetWMHints( xdisplay, xwindow, &wm_hints);
@@ -266,6 +285,8 @@ void wxTopLevelWindowX11::OnInternalIdle()
 
 bool wxTopLevelWindowX11::Show(bool show)
 {
 
 bool wxTopLevelWindowX11::Show(bool show)
 {
+    XSync( wxGlobalDisplay(), False );
+    
     // Nano-X has to force a size event,
     // else there's no initial size.
 #if wxUSE_NANOX
     // Nano-X has to force a size event,
     // else there's no initial size.
 #if wxUSE_NANOX
@@ -619,7 +640,7 @@ void wxTopLevelWindowX11::DoSetClientSize(int width, int height)
     size_hints.flags = PSize;
     size_hints.width = width + (oldSize.x - oldClientSize.x);
     size_hints.height = height + (oldSize.y - oldClientSize.y);
     size_hints.flags = PSize;
     size_hints.width = width + (oldSize.x - oldClientSize.x);
     size_hints.height = height + (oldSize.y - oldClientSize.y);
-    XSetWMNormalHints( (Display*) GetXDisplay(), (Window) GetMainWindow(),
+    XSetWMNormalHints( wxGlobalDisplay(), (Window) GetMainWindow(),
                        &size_hints);
 
     // This seems to be necessary or resizes don't get performed
                        &size_hints);
 
     // This seems to be necessary or resizes don't get performed
@@ -644,11 +665,11 @@ void wxTopLevelWindowX11::DoSetSize(int x, int y, int width, int height, int siz
     wxWindowX11::DoSetSize(x, y, width, height, sizeFlags);
 #endif
     XSync(wxGlobalDisplay(), False);
     wxWindowX11::DoSetSize(x, y, width, height, sizeFlags);
 #endif
     XSync(wxGlobalDisplay(), False);
-    Window window = (Window) m_mainWidget;
+    Window window = (Window) m_mainWindow;
     if (!window)
         return ;
 
     if (!window)
         return ;
 
-    Display *display = (Display*) GetXDisplay();
+    Display *display = wxGlobalDisplay();
     Window root = RootWindowOfScreen(DefaultScreenOfDisplay(display));
     Window parent_window = window,
         next_parent   = window;
     Window root = RootWindowOfScreen(DefaultScreenOfDisplay(display));
     Window parent_window = window,
         next_parent   = window;
@@ -708,7 +729,7 @@ void wxTopLevelWindowX11::DoSetSize(int x, int y, int width, int height, int siz
     size_hints.height = height;
     size_hints.x = x;
     size_hints.y = y;
     size_hints.height = height;
     size_hints.x = x;
     size_hints.y = y;
-    XSetWMNormalHints( (Display*) GetXDisplay(), (Window) GetMainWindow(),
+    XSetWMNormalHints( wxGlobalDisplay(), (Window) GetMainWindow(),
                        &size_hints);
 
     // This seems to be necessary or resizes don't get performed.
                        &size_hints);
 
     // This seems to be necessary or resizes don't get performed.
@@ -727,11 +748,11 @@ void wxTopLevelWindowX11::DoSetSize(int x, int y, int width, int height, int siz
 void wxTopLevelWindowX11::DoGetPosition(int *x, int *y) const
 {
     XSync(wxGlobalDisplay(), False);
 void wxTopLevelWindowX11::DoGetPosition(int *x, int *y) const
 {
     XSync(wxGlobalDisplay(), False);
-    Window window = (Window) m_mainWidget;
+    Window window = (Window) m_mainWindow;
     if (!window)
         return ;
 
     if (!window)
         return ;
 
-    Display *display = (Display*) GetXDisplay();
+    Display *display = wxGlobalDisplay();
     Window root = RootWindowOfScreen(DefaultScreenOfDisplay(display));
     Window parent_window = window,
         next_parent   = window;
     Window root = RootWindowOfScreen(DefaultScreenOfDisplay(display));
     Window parent_window = window,
         next_parent   = window;
@@ -758,7 +779,7 @@ void wxTopLevelWindowX11::DoGetPosition(int *x, int *y) const
     if (y) *y = yy;
 #else
     XWindowAttributes attr;
     if (y) *y = yy;
 #else
     XWindowAttributes attr;
-    Status status = XGetWindowAttributes((Display*) GetXDisplay(), parent_window, & attr);
+    Status status = XGetWindowAttributes( wxGlobalDisplay(), parent_window, & attr);
     if (status)
     {
         if (x) *x = attr.x;
     if (status)
     {
         if (x) *x = attr.x;
index 9533b1d1a84dd493cec30ce35ef5c69c69ddbf51..3f186d493769f5e5d53e5a4f2ba2cbbf9c31415a 100644 (file)
@@ -36,6 +36,7 @@
 #include "wx/msgdlg.h"
 #include "wx/frame.h"
 #include "wx/scrolwin.h"
 #include "wx/msgdlg.h"
 #include "wx/frame.h"
 #include "wx/scrolwin.h"
+#include "wx/scrolbar.h"
 #include "wx/module.h"
 #include "wx/menuitem.h"
 #include "wx/log.h"
 #include "wx/module.h"
 #include "wx/menuitem.h"
 #include "wx/log.h"
@@ -59,6 +60,7 @@
 // ----------------------------------------------------------------------------
 
 extern wxHashTable *wxWidgetHashTable;
 // ----------------------------------------------------------------------------
 
 extern wxHashTable *wxWidgetHashTable;
+extern wxHashTable *wxClientWidgetHashTable;
 static wxWindow* g_captureWindow = NULL;
 
 // ----------------------------------------------------------------------------
 static wxWindow* g_captureWindow = NULL;
 
 // ----------------------------------------------------------------------------
@@ -97,7 +99,10 @@ void wxWindowX11::Init()
     InitBase();
 
     // X11-specific
     InitBase();
 
     // X11-specific
-    m_mainWidget = (WXWindow) 0;
+    m_mainWindow = (WXWindow) 0;
+    m_clientWindow = (WXWindow) 0;
+    m_insertIntoMain = FALSE;
+    
     m_winCaptured = FALSE;
     m_needsInputFocus = FALSE;
     m_isShown = TRUE;
     m_winCaptured = FALSE;
     m_needsInputFocus = FALSE;
     m_isShown = TRUE;
@@ -139,7 +144,14 @@ bool wxWindowX11::Create(wxWindow *parent, wxWindowID id,
     m_foregroundColour = *wxBLACK;
     m_foregroundColour.CalcPixel( (WXColormap) cm ); 
 
     m_foregroundColour = *wxBLACK;
     m_foregroundColour.CalcPixel( (WXColormap) cm ); 
 
-    Window xparent = (Window) parent->GetMainWindow();
+    Window xparent = (Window) parent->GetClientWindow();
+    
+    // Add window's own scrollbars to main window, not to client window
+    if (parent->GetInsertIntoMain())
+    {
+        // wxLogDebug( "Inserted into main: %s", GetName().c_str() );
+        xparent = (Window) parent->GetMainWindow();
+    }
     
     wxSize size2(size);
     if (size2.x == -1)
     
     wxSize size2(size);
     if (size2.x == -1)
@@ -154,29 +166,89 @@ bool wxWindowX11::Create(wxWindow *parent, wxWindowID id,
        pos2.y = 0;
     
 #if !wxUSE_NANOX
        pos2.y = 0;
     
 #if !wxUSE_NANOX
+
+#if wxUSE_TWO_WINDOWS
+    bool need_two_windows = 
+        ((( wxSUNKEN_BORDER | wxRAISED_BORDER | wxSIMPLE_BORDER | wxHSCROLL | wxVSCROLL ) & m_windowStyle) != 0);
+#else
+    bool need_two_windows = FALSE;
+#endif
+
     XSetWindowAttributes xattributes;
     XSetWindowAttributes xattributes;
+    long xattributes_mask = 0;
     
     
-    long xattributes_mask =
-        CWBorderPixel | CWBackPixel;
-        
+    xattributes_mask |= CWBackPixel;
     xattributes.background_pixel = m_backgroundColour.GetPixel();
     xattributes.background_pixel = m_backgroundColour.GetPixel();
+    
+    xattributes_mask |= CWBorderPixel;
     xattributes.border_pixel = BlackPixel( xdisplay, xscreen );
     
     xattributes_mask |= CWEventMask;
     xattributes.border_pixel = BlackPixel( xdisplay, xscreen );
     
     xattributes_mask |= CWEventMask;
-    xattributes.event_mask = 
-        ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
-        ButtonMotionMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask |
-        KeymapStateMask | FocusChangeMask | ColormapChangeMask | StructureNotifyMask |
-        PropertyChangeMask | VisibilityChangeMask ;
-
-    if (HasFlag( wxNO_FULL_REPAINT_ON_RESIZE ))
+    
+    if (need_two_windows)
     {
     {
-        xattributes_mask |= CWBitGravity;
-        xattributes.bit_gravity = StaticGravity;
+        xattributes.event_mask = 
+            ExposureMask | StructureNotifyMask | ColormapChangeMask;
+
+        Window xwindow = XCreateWindow( xdisplay, xparent, pos2.x, pos2.y, size2.x, size2.y, 
+            0, DefaultDepth(xdisplay,xscreen), InputOutput, xvisual, xattributes_mask, &xattributes );
+    
+        XSetWindowBackgroundPixmap( xdisplay, xwindow, None );
+    
+        m_mainWindow = (WXWindow) xwindow;
+        wxAddWindowToTable( xwindow, (wxWindow*) this );
+    
+        XMapWindow( xdisplay, xwindow );
+    
+        xattributes.event_mask = 
+            ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
+            ButtonMotionMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask |
+            KeymapStateMask | FocusChangeMask | ColormapChangeMask | StructureNotifyMask |
+            PropertyChangeMask | VisibilityChangeMask ;
+
+        if (HasFlag( wxNO_FULL_REPAINT_ON_RESIZE ))
+        {
+            xattributes_mask |= CWBitGravity;
+            xattributes.bit_gravity = StaticGravity;
+        }
+
+        xwindow = XCreateWindow( xdisplay, xwindow, 0, 0, size2.x, size2.y, 
+            0, DefaultDepth(xdisplay,xscreen), InputOutput, xvisual, xattributes_mask, &xattributes );
+    
+        XSetWindowBackgroundPixmap( xdisplay, xwindow, None );
+    
+        m_clientWindow = (WXWindow) xwindow;
+        wxAddClientWindowToTable( xwindow, (wxWindow*) this );
+        
+        XMapWindow( xdisplay, xwindow );
     }
     }
+    else
+    {
+        // wxLogDebug( "No two windows needed %s", GetName().c_str() );
+    
+        xattributes.event_mask = 
+            ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
+            ButtonMotionMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask |
+            KeymapStateMask | FocusChangeMask | ColormapChangeMask | StructureNotifyMask |
+            PropertyChangeMask | VisibilityChangeMask ;
 
 
-    Window xwindow = XCreateWindow( xdisplay, xparent, pos2.x, pos2.y, size2.x, size2.y, 
-       0, DefaultDepth(xdisplay,xscreen), InputOutput, xvisual, xattributes_mask, &xattributes );
+        if (HasFlag( wxNO_FULL_REPAINT_ON_RESIZE ))
+        {
+            xattributes_mask |= CWBitGravity;
+            xattributes.bit_gravity = StaticGravity;
+        }
+
+        Window xwindow = XCreateWindow( xdisplay, xparent, pos2.x, pos2.y, size2.x, size2.y, 
+            0, DefaultDepth(xdisplay,xscreen), InputOutput, xvisual, xattributes_mask, &xattributes );
+            
+        XSetWindowBackgroundPixmap( xdisplay, xwindow, None );
+    
+        m_mainWindow = (WXWindow) xwindow;
+        m_clientWindow = m_mainWindow;
+        wxAddWindowToTable( xwindow, (wxWindow*) this );
+        
+        XMapWindow( xdisplay, xwindow );
+    }
 #else
 
     int extraFlags = GR_EVENT_MASK_CLOSE_REQ;
 #else
 
     int extraFlags = GR_EVENT_MASK_CLOSE_REQ;
@@ -192,24 +264,22 @@ bool wxWindowX11::Create(wxWindow *parent, wxWindowID id,
         ButtonMotionMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask |
         KeymapStateMask | FocusChangeMask | ColormapChangeMask | StructureNotifyMask |
         PropertyChangeMask );
         ButtonMotionMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask |
         KeymapStateMask | FocusChangeMask | ColormapChangeMask | StructureNotifyMask |
         PropertyChangeMask );
-#endif
     
     
-    m_mainWidget = (WXWindow) xwindow;
-
+    XSetWindowBackgroundPixmap( xdisplay, xwindow, None );
+    
+    m_mainWindow = (WXWindow) xwindow;
     wxAddWindowToTable( xwindow, (wxWindow*) this );
     wxAddWindowToTable( xwindow, (wxWindow*) this );
+    
+    XMapWindow( xdisplay, xwindow );
+#endif
 
     // Is a subwindow, so map immediately
     m_isShown = TRUE;
 
     // Is a subwindow, so map immediately
     m_isShown = TRUE;
-    XMapWindow( xdisplay, xwindow );
 
     // Without this, the cursor may not be restored properly (e.g. in splitter
     // sample).
     SetCursor(*wxSTANDARD_CURSOR);
     SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
 
     // Without this, the cursor may not be restored properly (e.g. in splitter
     // sample).
     SetCursor(*wxSTANDARD_CURSOR);
     SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
-    
-    // Set background to None which will prevent X11 from clearing the
-    // background comletely.
-    XSetWindowBackgroundPixmap( xdisplay, xwindow, None );
 
     // Don't call this, it can have nasty repercussions for composite controls,
     // for example
 
     // Don't call this, it can have nasty repercussions for composite controls,
     // for example
@@ -226,22 +296,25 @@ wxWindowX11::~wxWindowX11()
     
     m_isBeingDeleted = TRUE;
     
     
     m_isBeingDeleted = TRUE;
     
-    // X11-specific actions first
-    Window xwindow = (Window) m_mainWidget;
-
     if (m_parent)
         m_parent->RemoveChild( this );
 
     DestroyChildren();
 
     if (m_parent)
         m_parent->RemoveChild( this );
 
     DestroyChildren();
 
-    // Destroy the window
-    if (xwindow)
+    if (m_clientWindow != m_mainWindow)
     {
     {
-        XSelectInput( wxGlobalDisplay(), xwindow, NoEventMask);
-        wxDeleteWindowFromTable( xwindow );
+        // Destroy the cleint window
+        Window xwindow = (Window) m_clientWindow;
+        wxDeleteClientWindowFromTable( xwindow );
         XDestroyWindow( wxGlobalDisplay(), xwindow );
         XDestroyWindow( wxGlobalDisplay(), xwindow );
-        m_mainWidget = NULL;
+        m_clientWindow = NULL;
     }
     }
+        
+    // Destroy the window
+    Window xwindow = (Window) m_mainWindow;
+    wxDeleteWindowFromTable( xwindow );
+    XDestroyWindow( wxGlobalDisplay(), xwindow );
+    m_mainWindow = NULL;
 }
 
 // ---------------------------------------------------------------------------
 }
 
 // ---------------------------------------------------------------------------
@@ -250,7 +323,7 @@ wxWindowX11::~wxWindowX11()
 
 void wxWindowX11::SetFocus()
 {
 
 void wxWindowX11::SetFocus()
 {
-    Window xwindow = (Window) GetMainWindow();
+    Window xwindow = (Window) m_clientWindow;
     
     wxCHECK_RET( xwindow, wxT("invalid window") );
     
     
     wxCHECK_RET( xwindow, wxT("invalid window") );
     
@@ -292,19 +365,6 @@ wxWindow *wxWindowBase::FindFocus()
     return NULL;
 }
 
     return NULL;
 }
 
-wxWindow *wxWindowX11::GetFocusWidget()
-{
-   wxWindow *win = (wxWindow*) this;
-   while (!win->IsTopLevel())
-   {
-       win = win->GetParent();
-       if (!win)
-           return (wxWindow*) NULL;
-   }
-   
-   return win;
-}
-
 // Enabling/disabling handled by event loop, and not sending events
 // if disabled.
 bool wxWindowX11::Enable(bool enable)
 // Enabling/disabling handled by event loop, and not sending events
 // if disabled.
 bool wxWindowX11::Enable(bool enable)
@@ -319,18 +379,17 @@ bool wxWindowX11::Show(bool show)
 {
     wxWindowBase::Show(show);
 
 {
     wxWindowBase::Show(show);
 
-    Window xwin = (Window) GetXWindow();
-    Display *xdisp = (Display*) GetXDisplay();
+    Window xwindow = (Window) m_mainWindow;
+    Display *xdisp = wxGlobalDisplay();
     if (show)
     {
         // wxLogDebug( "Mapping window of type %s", GetName().c_str() );
     if (show)
     {
         // wxLogDebug( "Mapping window of type %s", GetName().c_str() );
-        XMapWindow(xdisp, xwin);
-        XSync(xdisp, False);
+        XMapWindow(xdisp, xwindow);
     }
     else
     {
         // wxLogDebug( "Unmapping window of type %s", GetName().c_str() );
     }
     else
     {
         // wxLogDebug( "Unmapping window of type %s", GetName().c_str() );
-        XUnmapWindow(xdisp, xwin);
+        XUnmapWindow(xdisp, xwindow);
     }
 
     return TRUE;
     }
 
     return TRUE;
@@ -339,15 +398,15 @@ bool wxWindowX11::Show(bool show)
 // Raise the window to the top of the Z order
 void wxWindowX11::Raise()
 {
 // Raise the window to the top of the Z order
 void wxWindowX11::Raise()
 {
-    if (m_mainWidget)
-        XRaiseWindow( wxGlobalDisplay(), (Window) m_mainWidget );
+    if (m_mainWindow)
+        XRaiseWindow( wxGlobalDisplay(), (Window) m_mainWindow );
 }
 
 // Lower the window to the bottom of the Z order
 void wxWindowX11::Lower()
 {
 }
 
 // Lower the window to the bottom of the Z order
 void wxWindowX11::Lower()
 {
-    if (m_mainWidget)
-        XLowerWindow( wxGlobalDisplay(), (Window) m_mainWidget );
+    if (m_mainWindow)
+        XLowerWindow( wxGlobalDisplay(), (Window) m_mainWindow );
 }
 
 void wxWindowX11::DoCaptureMouse()
 }
 
 void wxWindowX11::DoCaptureMouse()
@@ -365,7 +424,7 @@ void wxWindowX11::DoCaptureMouse()
     if (m_winCaptured)
         return;
 
     if (m_winCaptured)
         return;
 
-    Window xwindow = (Window) GetMainWindow();
+    Window xwindow = (Window) m_clientWindow;
 
     wxCHECK_RET( xwindow, wxT("invalid window") );
     
 
     wxCHECK_RET( xwindow, wxT("invalid window") );
     
@@ -395,44 +454,6 @@ void wxWindowX11::DoCaptureMouse()
             return;
         }
 
             return;
         }
 
-        // wxLogDebug("Grabbed pointer in %s", GetName().c_str() );
-
-#if 0
-        res = XGrabButton(wxGlobalDisplay(), AnyButton, AnyModifier,
-            (Window) GetMainWindow(),
-            FALSE,
-            ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
-               GrabModeAsync,
-               GrabModeAsync,
-            None,
-            None);
-       
-        if (res != GrabSuccess)
-        {
-            wxLogDebug("Failed to grab mouse buttons.");
-            XUngrabPointer(wxGlobalDisplay(), CurrentTime);
-            return;
-        }
-#endif
-
-#if 0
-        res = XGrabKeyboard(wxGlobalDisplay(), (Window) GetMainWindow(),
-            ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask,
-            FALSE,
-            GrabModeAsync,
-               GrabModeAsync,
-            CurrentTime);
-
-        if (res != GrabSuccess)
-        {
-            wxLogDebug("Failed to grab keyboard.");
-            XUngrabPointer(wxGlobalDisplay(), CurrentTime);
-            XUngrabButton(wxGlobalDisplay(), AnyButton, AnyModifier,
-                (Window) GetMainWindow());
-            return;
-        }
-#endif
-       
         m_winCaptured = TRUE;
     }
 }
         m_winCaptured = TRUE;
     }
 }
@@ -444,15 +465,11 @@ void wxWindowX11::DoReleaseMouse()
     if ( !m_winCaptured )
         return;
 
     if ( !m_winCaptured )
         return;
 
-    Window xwindow = (Window) GetMainWindow();
+    Window xwindow = (Window) m_clientWindow;
 
     if (xwindow)
     {
         XUngrabPointer( wxGlobalDisplay(), CurrentTime );
 
     if (xwindow)
     {
         XUngrabPointer( wxGlobalDisplay(), CurrentTime );
-#if 0
-        XUngrabButton( wxGlobalDisplay(), AnyButton, AnyModifier, xwindow);
-        XUngrabKeyboard( wxGlobalDisplay(), CurrentTime );
-#endif
     }
     
     // wxLogDebug( "Ungrabbed pointer in %s", GetName().c_str() );
     }
     
     // wxLogDebug( "Ungrabbed pointer in %s", GetName().c_str() );
@@ -479,7 +496,7 @@ bool wxWindowX11::SetCursor(const wxCursor& cursor)
         return FALSE;
     }
 
         return FALSE;
     }
 
-    Window xwindow = (Window) GetMainWindow();
+    Window xwindow = (Window) m_clientWindow;
 
     wxCHECK_MSG( xwindow, FALSE, wxT("invalid window") );
     
 
     wxCHECK_MSG( xwindow, FALSE, wxT("invalid window") );
     
@@ -499,7 +516,7 @@ bool wxWindowX11::SetCursor(const wxCursor& cursor)
 // Coordinates relative to the window
 void wxWindowX11::WarpPointer (int x, int y)
 {
 // Coordinates relative to the window
 void wxWindowX11::WarpPointer (int x, int y)
 {
-    Window xwindow = (Window) GetMainWindow();
+    Window xwindow = (Window) m_clientWindow;
 
     wxCHECK_RET( xwindow, wxT("invalid window") );
     
 
     wxCHECK_RET( xwindow, wxT("invalid window") );
     
@@ -532,7 +549,7 @@ void wxWindowX11::ScrollWindow(int dx, int dy, const wxRect *rect)
         m_clearRegion.Intersect( 0, 0, cw, ch );
     }
     
         m_clearRegion.Intersect( 0, 0, cw, ch );
     }
     
-    Window xwindow = (Window) GetMainWindow();
+    Window xwindow = (Window) GetClientWindow();
 
     wxCHECK_RET( xwindow, wxT("invalid window") );
 
 
     wxCHECK_RET( xwindow, wxT("invalid window") );
 
@@ -560,9 +577,13 @@ void wxWindowX11::ScrollWindow(int dx, int dy, const wxRect *rect)
         GetClientSize( &cw, &ch );
     }
     
         GetClientSize( &cw, &ch );
     }
     
+#if wxUSE_TWO_WINDOWS
+    wxPoint offset( 0,0 );
+#else
     wxPoint offset = GetClientAreaOrigin();
     s_x += offset.x;
     s_y += offset.y;
     wxPoint offset = GetClientAreaOrigin();
     s_x += offset.x;
     s_y += offset.y;
+#endif
         
     int w = cw - abs(dx);
     int h = ch - abs(dy);
         
     int w = cw - abs(dx);
     int h = ch - abs(dy);
@@ -644,7 +665,7 @@ bool wxWindowX11::PreResize()
 // Get total size
 void wxWindowX11::DoGetSize(int *x, int *y) const
 {
 // Get total size
 void wxWindowX11::DoGetSize(int *x, int *y) const
 {
-    Window xwindow = (Window) GetMainWindow();
+    Window xwindow = (Window) m_mainWindow;
 
     wxCHECK_RET( xwindow, wxT("invalid window") );
     
 
     wxCHECK_RET( xwindow, wxT("invalid window") );
     
@@ -663,7 +684,7 @@ void wxWindowX11::DoGetSize(int *x, int *y) const
 
 void wxWindowX11::DoGetPosition(int *x, int *y) const
 {
 
 void wxWindowX11::DoGetPosition(int *x, int *y) const
 {
-    Window window = (Window) m_mainWidget;
+    Window window = (Window) m_mainWindow;
     if (window)
     {
         //XSync(wxGlobalDisplay(), False);
     if (window)
     {
         //XSync(wxGlobalDisplay(), False);
@@ -692,7 +713,7 @@ void wxWindowX11::DoScreenToClient(int *x, int *y) const
 {
     Display *display = wxGlobalDisplay();
     Window rootWindow = RootWindowOfScreen(DefaultScreenOfDisplay(display));
 {
     Display *display = wxGlobalDisplay();
     Window rootWindow = RootWindowOfScreen(DefaultScreenOfDisplay(display));
-    Window thisWindow = (Window) m_mainWidget;
+    Window thisWindow = (Window) m_clientWindow;
 
     Window childWindow;
     int xx = *x;
 
     Window childWindow;
     int xx = *x;
@@ -704,7 +725,7 @@ void wxWindowX11::DoClientToScreen(int *x, int *y) const
 {
     Display *display = wxGlobalDisplay();
     Window rootWindow = RootWindowOfScreen(DefaultScreenOfDisplay(display));
 {
     Display *display = wxGlobalDisplay();
     Window rootWindow = RootWindowOfScreen(DefaultScreenOfDisplay(display));
-    Window thisWindow = (Window) m_mainWidget;
+    Window thisWindow = (Window) m_clientWindow;
 
     Window childWindow;
     int xx = *x;
 
     Window childWindow;
     int xx = *x;
@@ -716,11 +737,10 @@ void wxWindowX11::DoClientToScreen(int *x, int *y) const
 // Get size *available for subwindows* i.e. excluding menu bar etc.
 void wxWindowX11::DoGetClientSize(int *x, int *y) const
 {
 // Get size *available for subwindows* i.e. excluding menu bar etc.
 void wxWindowX11::DoGetClientSize(int *x, int *y) const
 {
-    Window window = (Window) m_mainWidget;
+    Window window = (Window) m_mainWindow;
 
     if (window)
     {
 
     if (window)
     {
-        //XSync(wxGlobalDisplay(), False);  // Is this really a good idea?
         XWindowAttributes attr;
         Status status = XGetWindowAttributes( wxGlobalDisplay(), window, &attr );
         wxASSERT(status);
         XWindowAttributes attr;
         Status status = XGetWindowAttributes( wxGlobalDisplay(), window, &attr );
         wxASSERT(status);
@@ -736,8 +756,8 @@ void wxWindowX11::DoGetClientSize(int *x, int *y) const
 void wxWindowX11::DoSetSize(int x, int y, int width, int height, int sizeFlags)
 {
     //    wxLogDebug("DoSetSize: %s (%ld) %d, %d %dx%d", GetClassInfo()->GetClassName(), GetId(), x, y, width, height);
 void wxWindowX11::DoSetSize(int x, int y, int width, int height, int sizeFlags)
 {
     //    wxLogDebug("DoSetSize: %s (%ld) %d, %d %dx%d", GetClassInfo()->GetClassName(), GetId(), x, y, width, height);
-
-    Window xwindow = (Window) GetMainWindow();
+    
+    Window xwindow = (Window) m_mainWindow;
 
     wxCHECK_RET( xwindow, wxT("invalid window") );
 
 
     wxCHECK_RET( xwindow, wxT("invalid window") );
 
@@ -749,8 +769,7 @@ void wxWindowX11::DoSetSize(int x, int y, int width, int height, int sizeFlags)
     int new_y = attr.y;
     int new_w = attr.width;
     int new_h = attr.height;
     int new_y = attr.y;
     int new_w = attr.width;
     int new_h = attr.height;
-            
-
+    
     if (x != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
     {
         int yy = 0;
     if (x != -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
     {
         int yy = 0;
@@ -788,41 +807,30 @@ void wxWindowX11::DoSetSize(int x, int y, int width, int height, int sizeFlags)
 void wxWindowX11::DoSetClientSize(int width, int height)
 {
     //    wxLogDebug("DoSetClientSize: %s (%ld) %dx%d", GetClassInfo()->GetClassName(), GetId(), width, height);
 void wxWindowX11::DoSetClientSize(int width, int height)
 {
     //    wxLogDebug("DoSetClientSize: %s (%ld) %dx%d", GetClassInfo()->GetClassName(), GetId(), width, height);
-
-    Window xwindow = (Window) GetMainWindow();
+    
+    Window xwindow = (Window) m_mainWindow;
 
     wxCHECK_RET( xwindow, wxT("invalid window") );
 
 
     wxCHECK_RET( xwindow, wxT("invalid window") );
 
-#if 1
-
     XResizeWindow( wxGlobalDisplay(), xwindow, width, height );
     XResizeWindow( wxGlobalDisplay(), xwindow, width, height );
-
-#if 0
-    wxSizeEvent event(wxSize(width, height), GetId());
-    event.SetEventObject(this);
-    GetEventHandler()->ProcessEvent(event);
-#endif
     
     
-#else
-
-    XWindowAttributes attr;
-    Status status = XGetWindowAttributes( wxGlobalDisplay(), xwindow, &attr );
-    wxCHECK_RET( status, wxT("invalid window attributes") );
+    if (m_mainWindow != m_clientWindow)
+    {
+        xwindow = (Window) m_clientWindow;
         
         
-    int new_x = attr.x;
-    int new_y = attr.y;
-    int new_w = attr.width;
-    int new_h = attr.height;
-            
-    if (width != -1)
-        new_w = width;
+        if (HasFlag( wxSUNKEN_BORDER) || HasFlag( wxRAISED_BORDER))
+        {
+            width -= 4;
+            height -= 4;
+        } else
+        if (HasFlag( wxSIMPLE_BORDER ))
+        {
+            width -= 2;
+            height -= 2;
+        }
         
         
-    if (height != -1)
-        new_h = height;
-    
-    DoMoveWindow( new_x, new_y, new_w, new_h );
-    
-#endif
+        XResizeWindow( wxGlobalDisplay(), xwindow, width, height );
+    }
 }
 
 // For implementation purposes - sometimes decorations make the client area
 }
 
 // For implementation purposes - sometimes decorations make the client area
@@ -832,6 +840,70 @@ wxPoint wxWindowX11::GetClientAreaOrigin() const
     return wxPoint(0, 0);
 }
 
     return wxPoint(0, 0);
 }
 
+void wxWindowX11::DoMoveWindow(int x, int y, int width, int height)
+{
+    Window xwindow = (Window) m_mainWindow;
+
+    wxCHECK_RET( xwindow, wxT("invalid window") );
+
+#if !wxUSE_NANOX
+
+    XMoveResizeWindow( wxGlobalDisplay(), xwindow, x, y, width, height );
+    if (m_mainWindow != m_clientWindow)
+    {
+        xwindow = (Window) m_clientWindow;
+        
+        if (HasFlag( wxSUNKEN_BORDER) || HasFlag( wxRAISED_BORDER))
+        {
+            x = 2;
+            y = 2;
+            width -= 4;
+            height -= 4;
+        } else
+        if (HasFlag( wxSIMPLE_BORDER ))
+        {
+            x = 1;
+            y = 1;
+            width -= 2;
+            height -= 2;
+        } else
+        {
+            x = 0;
+            y = 0;
+        }
+        
+        wxWindow *window = (wxWindow*) this;
+        wxScrollBar *sb = window->GetScrollbar( wxHORIZONTAL );
+        if (sb && sb->IsShown())
+        {
+            wxSize size = sb->GetSize();
+            height -= size.y;
+        }
+        sb = window->GetScrollbar( wxVERTICAL );
+        if (sb && sb->IsShown())
+        {
+            wxSize size = sb->GetSize();
+            width -= size.x;
+        }
+        
+        XMoveResizeWindow( wxGlobalDisplay(), xwindow, x, y, width, height );
+    }
+    
+#else    
+
+    XWindowChanges windowChanges;
+    windowChanges.x = x;
+    windowChanges.y = y;
+    windowChanges.width = width;
+    windowChanges.height = height;
+    windowChanges.stack_mode = 0;
+    int valueMask = CWX | CWY | CWWidth | CWHeight;
+
+    XConfigureWindow( wxGlobalDisplay(), xwindow, valueMask, &windowChanges );
+    
+#endif
+}
+
 void wxWindowX11::SetSizeHints(int minW, int minH, int maxW, int maxH, int incW, int incH)
 {
     m_minWidth = minW;
 void wxWindowX11::SetSizeHints(int minW, int minH, int maxW, int maxH, int incW, int incH)
 {
     m_minWidth = minW;
@@ -862,48 +934,7 @@ void wxWindowX11::SetSizeHints(int minW, int minH, int maxW, int maxH, int incW,
         sizeHints.height_inc = incH;
     }
 
         sizeHints.height_inc = incH;
     }
 
-    XSetWMNormalHints(wxGlobalDisplay(), (Window) GetMainWindow(), & sizeHints);
-#endif
-}
-
-void wxWindowX11::DoMoveWindow(int x, int y, int width, int height)
-{
-    Window xwindow = (Window) GetMainWindow();
-
-    wxCHECK_RET( xwindow, wxT("invalid window") );
-
-#if !wxUSE_NANOX
-
-    XWindowAttributes attr;
-    Status status = XGetWindowAttributes( wxGlobalDisplay(), xwindow, &attr );
-    wxCHECK_RET( status, wxT("invalid window attributes") );
-    
-    if (attr.width == width && attr.height == height)
-    {
-        XMoveWindow( wxGlobalDisplay(), xwindow, x, y );
-        return;
-    }
-    
-    if (attr.x == x && attr.y == y)
-    {
-        XResizeWindow( wxGlobalDisplay(), xwindow, width, height );
-        return;
-    }
-    
-    XMoveResizeWindow( wxGlobalDisplay(), xwindow, x, y, width, height );
-    
-#else    
-
-    XWindowChanges windowChanges;
-    windowChanges.x = x;
-    windowChanges.y = y;
-    windowChanges.width = width;
-    windowChanges.height = height;
-    windowChanges.stack_mode = 0;
-    int valueMask = CWX | CWY | CWWidth | CWHeight;
-
-    XConfigureWindow( wxGlobalDisplay(), xwindow, valueMask, &windowChanges );
-    
+    XSetWMNormalHints(wxGlobalDisplay(), (Window) m_mainWindow, &sizeHints );
 #endif
 }
 
 #endif
 }
 
@@ -915,7 +946,7 @@ int wxWindowX11::GetCharHeight() const
 {
     wxCHECK_MSG( m_font.Ok(), 0, "valid window font needed" );
 
 {
     wxCHECK_MSG( m_font.Ok(), 0, "valid window font needed" );
 
-    WXFontStructPtr pFontStruct = m_font.GetFontStruct(1.0, GetXDisplay());
+    WXFontStructPtr pFontStruct = m_font.GetFontStruct(1.0, wxGlobalDisplay());
 
     int direction, ascent, descent;
     XCharStruct overall;
 
     int direction, ascent, descent;
     XCharStruct overall;
@@ -930,7 +961,7 @@ int wxWindowX11::GetCharWidth() const
 {
     wxCHECK_MSG( m_font.Ok(), 0, "valid window font needed" );
 
 {
     wxCHECK_MSG( m_font.Ok(), 0, "valid window font needed" );
 
-    WXFontStructPtr pFontStruct = m_font.GetFontStruct(1.0, GetXDisplay());
+    WXFontStructPtr pFontStruct = m_font.GetFontStruct(1.0, wxGlobalDisplay());
 
     int direction, ascent, descent;
     XCharStruct overall;
 
     int direction, ascent, descent;
     XCharStruct overall;
@@ -950,7 +981,7 @@ void wxWindowX11::GetTextExtent(const wxString& string,
 
     wxCHECK_RET( fontToUse.Ok(), wxT("invalid font") );
 
 
     wxCHECK_RET( fontToUse.Ok(), wxT("invalid font") );
 
-    WXFontStructPtr pFontStruct = fontToUse.GetFontStruct(1.0, GetXDisplay());
+    WXFontStructPtr pFontStruct = fontToUse.GetFontStruct(1.0, wxGlobalDisplay());
 
     int direction, ascent, descent2;
     XCharStruct overall;
 
     int direction, ascent, descent2;
     XCharStruct overall;
@@ -1018,9 +1049,15 @@ void wxWindowX11::Refresh(bool eraseBack, const wxRect *rect)
 
 void wxWindowX11::Update()
 {
 
 void wxWindowX11::Update()
 {
+    if (m_updateNcArea)
+    {
+        // Send nc paint events.
+        SendNcPaintEvents();
+    }
+        
     if (!m_updateRegion.IsEmpty())
     {
     if (!m_updateRegion.IsEmpty())
     {
-        //        wxLogDebug("wxWindowX11::Update: %s", GetClassInfo()->GetClassName());
+        // wxLogDebug("wxWindowX11::Update: %s", GetClassInfo()->GetClassName());
         // Actually send erase events.
         SendEraseEvents();
         
         // Actually send erase events.
         SendEraseEvents();
         
@@ -1031,17 +1068,17 @@ void wxWindowX11::Update()
 
 void wxWindowX11::Clear()
 {
 
 void wxWindowX11::Clear()
 {
-    wxClientDC dc((wxWindow*) this);
-    wxBrush brush(GetBackgroundColour(), wxSOLID);
-    dc.SetBackground(brush);
-    dc.Clear();
+//    wxClientDC dc((wxWindow*) this);
+//    wxBrush brush(GetBackgroundColour(), wxSOLID);
+//    dc.SetBackground(brush);
+//    dc.Clear();
 }
 
 void wxWindowX11::SendEraseEvents()
 {
     if (m_clearRegion.IsEmpty()) return;
     
 }
 
 void wxWindowX11::SendEraseEvents()
 {
     if (m_clearRegion.IsEmpty()) return;
     
-    wxWindowDC dc( (wxWindow*)this );
+    wxClientDC dc( (wxWindow*)this );
     dc.SetClippingRegion( m_clearRegion );
     
     wxEraseEvent erase_event( GetId(), &dc );
     dc.SetClippingRegion( m_clearRegion );
     
     wxEraseEvent erase_event( GetId(), &dc );
@@ -1049,7 +1086,7 @@ void wxWindowX11::SendEraseEvents()
 
     if (!GetEventHandler()->ProcessEvent(erase_event))
     {
 
     if (!GetEventHandler()->ProcessEvent(erase_event))
     {
-        Window xwindow = (Window) GetMainWindow();
+        Window xwindow = (Window) m_clientWindow;
         Display *xdisplay = wxGlobalDisplay();
         GC xgc = XCreateGC( xdisplay, xwindow, 0, NULL );
         XSetFillStyle( xdisplay, xgc, FillSolid );
         Display *xdisplay = wxGlobalDisplay();
         GC xgc = XCreateGC( xdisplay, xwindow, 0, NULL );
         XSetFillStyle( xdisplay, xgc, FillSolid );
@@ -1073,10 +1110,6 @@ void wxWindowX11::SendPaintEvents()
 
     m_clipPaintRegion = TRUE;
     
 
     m_clipPaintRegion = TRUE;
     
-    wxNcPaintEvent nc_paint_event( GetId() );
-    nc_paint_event.SetEventObject( this );
-    GetEventHandler()->ProcessEvent( nc_paint_event );
-
     wxPaintEvent paint_event( GetId() );
     paint_event.SetEventObject( this );
     GetEventHandler()->ProcessEvent( paint_event );
     wxPaintEvent paint_event( GetId() );
     paint_event.SetEventObject( this );
     GetEventHandler()->ProcessEvent( paint_event );
@@ -1086,6 +1119,13 @@ void wxWindowX11::SendPaintEvents()
     m_clipPaintRegion = FALSE;
 }
 
     m_clipPaintRegion = FALSE;
 }
 
+void wxWindowX11::SendNcPaintEvents()
+{
+    wxNcPaintEvent nc_paint_event( GetId() );
+    nc_paint_event.SetEventObject( this );
+    GetEventHandler()->ProcessEvent( nc_paint_event );
+}
+
 // ----------------------------------------------------------------------------
 // event handlers
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // event handlers
 // ----------------------------------------------------------------------------
@@ -1158,28 +1198,53 @@ void wxDeleteWindowFromTable(Window w)
 }
 
 // ----------------------------------------------------------------------------
 }
 
 // ----------------------------------------------------------------------------
-// add/remove window from the table
+// function which maintain the global hash table mapping client widgets
 // ----------------------------------------------------------------------------
 
 // ----------------------------------------------------------------------------
 
-// ----------------------------------------------------------------------------
-// X11-specific accessors
-// ----------------------------------------------------------------------------
+bool wxAddClientWindowToTable(Window w, wxWindow *win)
+{
+    wxWindow *oldItem = NULL;
+    if ((oldItem = (wxWindow *)wxClientWidgetHashTable->Get ((long) w)))
+    {
+        wxLogDebug("Client window table clash: new window is %ld, %s",
+                   (long)w, win->GetClassInfo()->GetClassName());
+        return FALSE;
+    }
+
+    wxClientWidgetHashTable->Put((long) w, win);
+
+    wxLogTrace("widget", "XWindow 0x%08x <-> window %p (%s)",
+               w, win, win->GetClassInfo()->GetClassName());
 
 
-// Get the underlying X window
-WXWindow wxWindowX11::GetXWindow() const
+    return TRUE;
+}
+
+wxWindow *wxGetClientWindowFromTable(Window w)
 {
 {
-    return GetMainWindow();
+    return (wxWindow *)wxClientWidgetHashTable->Get((long) w);
 }
 
 }
 
-// Get the underlying X display
-WXDisplay *wxWindowX11::GetXDisplay() const
+void wxDeleteClientWindowFromTable(Window w)
 {
 {
-    return wxGetDisplay();
+    wxClientWidgetHashTable->Delete((long)w);
 }
 
 }
 
+// ----------------------------------------------------------------------------
+// add/remove window from the table
+// ----------------------------------------------------------------------------
+
+// ----------------------------------------------------------------------------
+// X11-specific accessors
+// ----------------------------------------------------------------------------
+
 WXWindow wxWindowX11::GetMainWindow() const
 {
 WXWindow wxWindowX11::GetMainWindow() const
 {
-    return m_mainWidget;
+    return m_mainWindow;
+}
+
+WXWindow wxWindowX11::GetClientWindow() const
+{
+    return m_clientWindow;
 }
 
 // ----------------------------------------------------------------------------
 }
 
 // ----------------------------------------------------------------------------