]> git.saurik.com Git - wxWidgets.git/blobdiff - src/x11/window.cpp
Try this again
[wxWidgets.git] / src / x11 / window.cpp
index 9fa7e4d83fc598d9ac8478990fed9f005d8a85f4..8ee15a5f5d7162d67cd3d5614638e3843bb27a77 100644 (file)
@@ -40,6 +40,7 @@
 #include "wx/module.h"
 #include "wx/menuitem.h"
 #include "wx/log.h"
+#include "wx/fontutil.h"
 #include "wx/univ/renderer.h"
 
 #if  wxUSE_DRAG_AND_DROP
@@ -127,15 +128,6 @@ bool wxWindowX11::Create(wxWindow *parent, wxWindowID id,
 
     parent->AddChild(this);
 
-    int w = size.GetWidth();
-    int h = size.GetHeight();
-    int x = size.GetX();
-    int y = size.GetY();
-    if (w == -1) w = 20;
-    if (h == -1) h = 20;
-    if (x == -1) x = 0;
-    if (y == -1) y = 0;
-
     Display *xdisplay = (Display*) wxGlobalDisplay();
     int xscreen = DefaultScreen( xdisplay );
     Visual *xvisual = DefaultVisual( xdisplay, xscreen );
@@ -147,7 +139,7 @@ bool wxWindowX11::Create(wxWindow *parent, wxWindowID id,
     m_foregroundColour = *wxBLACK;
     m_foregroundColour.CalcPixel( (WXColormap) cm ); 
 
-    Window xparent = (Window) parent->GetClientWindow();
+    Window xparent = (Window) parent->GetClientAreaWindow();
     
     // Add window's own scrollbars to main window, not to client window
     if (parent->GetInsertIntoMain())
@@ -156,20 +148,22 @@ bool wxWindowX11::Create(wxWindow *parent, wxWindowID id,
         xparent = (Window) parent->GetMainWindow();
     }
     
+    // Size (not including the border) must be nonzero (or a Value error results)!
+    // Note: The Xlib manual doesn't mention this restriction of XCreateWindow.
     wxSize size2(size);
-    if (size2.x == -1)
-       size2.x = 20;
-    if (size2.y == -1)
-       size2.y = 20;
+    if (size2.x <= 0)
+        size2.x = 20;
+    if (size2.y <= 0)
+        size2.y = 20;
 
     wxPoint pos2(pos);
     if (pos2.x == -1)
-       pos2.x = 0;
+        pos2.x = 0;
     if (pos2.y == -1)
-       pos2.y = 0;
-    
+        pos2.y = 0;
+        
 #if wxUSE_TWO_WINDOWS
-    bool need_two_windows = 
+    bool need_two_windows =
         ((( wxSUNKEN_BORDER | wxRAISED_BORDER | wxSIMPLE_BORDER | wxHSCROLL | wxVSCROLL ) & m_windowStyle) != 0);
 #else
     bool need_two_windows = FALSE;
@@ -242,18 +236,26 @@ bool wxWindowX11::Create(wxWindow *parent, wxWindowID id,
             pos2.y = 2;
             size2.x -= 4;
             size2.y -= 4;
-        } else
-        if (HasFlag( wxSIMPLE_BORDER ))
+        } 
+        else if (HasFlag( wxSIMPLE_BORDER ))
         {
             pos2.x = 1;
             pos2.y = 1;
             size2.x -= 2;
             size2.y -= 2;
-        } else
+        } 
+        else
         {
             pos2.x = 0;
             pos2.y = 0;
         }
+
+        // Make again sure the size is nonzero.
+        if (size2.x <= 0)
+            size2.x = 1;
+        if (size2.y <= 0)
+            size2.y = 1;
+
 #if wxUSE_NANOX        
         backColor = GR_RGB(m_backgroundColour.Red(), m_backgroundColour.Green(), m_backgroundColour.Blue());
         foreColor = GR_RGB(m_foregroundColour.Red(), m_foregroundColour.Green(), m_foregroundColour.Blue());
@@ -306,7 +308,7 @@ bool wxWindowX11::Create(wxWindow *parent, wxWindowID id,
             xattributes_mask |= CWBitGravity;
             xattributes.bit_gravity = NorthWestGravity;
         }
-
+        
         Window xwindow = XCreateWindow( xdisplay, xparent, pos2.x, pos2.y, size2.x, size2.y, 
             0, DefaultDepth(xdisplay,xscreen), InputOutput, xvisual, xattributes_mask, &xattributes );
 #endif
@@ -339,7 +341,7 @@ bool wxWindowX11::Create(wxWindow *parent, wxWindowID id,
 wxWindowX11::~wxWindowX11()
 {
     if (g_captureWindow == this)
-       g_captureWindow = NULL;
+        g_captureWindow = NULL;
     
     m_isBeingDeleted = TRUE;
     
@@ -489,7 +491,7 @@ void wxWindowX11::DoCaptureMouse()
             FALSE,
             ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask,
             GrabModeAsync,
-               GrabModeAsync,
+            GrabModeAsync,
             None,
             None, /* cursor */ // TODO: This may need to be set to the cursor of this window
             CurrentTime );
@@ -497,12 +499,11 @@ void wxWindowX11::DoCaptureMouse()
         if (res != GrabSuccess)
         {
             wxString msg;
-            msg.Printf("Failed to grab pointer for window %s", this->GetClassInfo()->GetClassName());
+            msg.Printf(wxT("Failed to grab pointer for window %s"), this->GetClassInfo()->GetClassName());
             wxLogDebug(msg);
             if (res == GrabNotViewable)
-            {
-                wxLogDebug("This is not a viewable window - perhaps not shown yet?");
-            }
+                wxLogDebug( wxT("This is not a viewable window - perhaps not shown yet?") );
+                
             g_captureWindow = NULL;
             return;
         }
@@ -602,7 +603,7 @@ void wxWindowX11::ScrollWindow(int dx, int dy, const wxRect *rect)
         m_clearRegion.Intersect( 0, 0, cw, ch );
     }
     
-    Window xwindow = (Window) GetClientWindow();
+    Window xwindow = (Window) GetClientAreaWindow();
 
     wxCHECK_RET( xwindow, wxT("invalid window") );
 
@@ -987,6 +988,17 @@ int wxWindowX11::GetCharHeight() const
 {
     wxCHECK_MSG( m_font.Ok(), 0, "valid window font needed" );
 
+#if wxUSE_UNICODE
+    // There should be an easier way.
+    PangoLayout *layout = pango_layout_new( wxTheApp->GetPangoContext() );
+    pango_layout_set_font_description( layout, GetFont().GetNativeFontInfo()->description );
+    pango_layout_set_text(layout, "H", 1 );
+    int w,h;
+    pango_layout_get_pixel_size(layout, &w, &h);
+    g_object_unref( G_OBJECT( layout ) );
+    
+    return h;
+#else
     WXFontStructPtr pFontStruct = m_font.GetFontStruct(1.0, wxGlobalDisplay());
 
     int direction, ascent, descent;
@@ -996,12 +1008,24 @@ int wxWindowX11::GetCharHeight() const
 
     //  return (overall.ascent + overall.descent);
     return (ascent + descent);
+#endif
 }
 
 int wxWindowX11::GetCharWidth() const
 {
     wxCHECK_MSG( m_font.Ok(), 0, "valid window font needed" );
 
+#if wxUSE_UNICODE
+    // There should be an easier way.
+    PangoLayout *layout = pango_layout_new( wxTheApp->GetPangoContext() );
+    pango_layout_set_font_description( layout, GetFont().GetNativeFontInfo()->description );
+    pango_layout_set_text(layout, "H", 1 );
+    int w,h;
+    pango_layout_get_pixel_size(layout, &w, &h);
+    g_object_unref( G_OBJECT( layout ) );
+    
+    return w;
+#else
     WXFontStructPtr pFontStruct = m_font.GetFontStruct(1.0, wxGlobalDisplay());
 
     int direction, ascent, descent;
@@ -1010,6 +1034,7 @@ int wxWindowX11::GetCharWidth() const
         &descent, &overall);
 
     return overall.width;
+#endif
 }
 
 void wxWindowX11::GetTextExtent(const wxString& string,
@@ -1022,18 +1047,45 @@ void wxWindowX11::GetTextExtent(const wxString& string,
 
     wxCHECK_RET( fontToUse.Ok(), wxT("invalid font") );
 
+    if (string.IsEmpty())
+    {
+        if (x) (*x) = 0;
+        if (y) (*y) = 0;
+        return;
+    }
+
+#if wxUSE_UNICODE
+    PangoLayout *layout = pango_layout_new( wxTheApp->GetPangoContext() );
+    
+    PangoFontDescription *desc = fontToUse.GetNativeFontInfo()->description;
+    pango_layout_set_font_description(layout, desc);
+    
+    const wxCharBuffer data = wxConvUTF8.cWC2MB( string );
+    pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data ));
+        
+    PangoLayoutLine *line = (PangoLayoutLine *)pango_layout_get_lines(layout)->data;
+
+    
+    PangoRectangle rect;
+    pango_layout_line_get_extents(line, NULL, &rect);
+    
+    if (x) (*x) = (wxCoord) (rect.width / PANGO_SCALE);
+    if (y) (*y) = (wxCoord) (rect.height / PANGO_SCALE);
+    if (descent)
+    {
+        // Do something about metrics here
+        (*descent) = 0;
+    }
+    if (externalLeading) (*externalLeading) = 0;  // ??
+
+    g_object_unref( G_OBJECT( layout ) );
+#else
     WXFontStructPtr pFontStruct = fontToUse.GetFontStruct(1.0, wxGlobalDisplay());
 
     int direction, ascent, descent2;
     XCharStruct overall;
     int slen = string.Len();
 
-#if 0
-    if (use16)
-        XTextExtents16((XFontStruct*) pFontStruct, (XChar2b *) (char*) (const char*) string, slen, &direction,
-        &ascent, &descent2, &overall);
-#endif
-
     XTextExtents((XFontStruct*) pFontStruct, (char*) string.c_str(), slen,
                  &direction, &ascent, &descent2, &overall);
 
@@ -1045,7 +1097,7 @@ void wxWindowX11::GetTextExtent(const wxString& string,
         *descent = descent2;
     if (externalLeading)
         *externalLeading = 0;
-
+#endif
 }
 
 // ----------------------------------------------------------------------------
@@ -1129,7 +1181,7 @@ void wxWindowX11::SendEraseEvents()
     if (!GetEventHandler()->ProcessEvent(erase_event) )
     {
         Display *xdisplay = wxGlobalDisplay();
-        Window xwindow = (Window) GetClientWindow();
+        Window xwindow = (Window) GetClientAreaWindow();
         XSetForeground( xdisplay, g_eraseGC, m_backgroundColour.GetPixel() );
         
         wxRegionIterator upd( m_clearRegion );
@@ -1241,8 +1293,9 @@ void wxWindowX11::OnInternalIdle()
         wxString msg;
         msg.Printf("Setting focus for %s from OnInternalIdle\n", GetClassInfo()->GetClassName());
         printf(msg.c_str());
-#endif        
-       SetFocus();
+#endif
+        SetFocus();
+        
         // If it couldn't set the focus now, there's
         // no point in trying again.
         m_needsInputFocus = FALSE;
@@ -1259,15 +1312,15 @@ bool wxAddWindowToTable(Window w, wxWindow *win)
     wxWindow *oldItem = NULL;
     if ((oldItem = (wxWindow *)wxWidgetHashTable->Get ((long) w)))
     {
-        wxLogDebug("Widget table clash: new widget is %ld, %s",
-                   (long)w, win->GetClassInfo()->GetClassName());
+        wxLogDebug( wxT("Widget table clash: new widget is %ld, %s"),
+                    (long)w, win->GetClassInfo()->GetClassName());
         return FALSE;
     }
 
     wxWidgetHashTable->Put((long) w, win);
 
-    wxLogTrace("widget", "XWindow 0x%08x <-> window %p (%s)",
-               w, win, win->GetClassInfo()->GetClassName());
+    wxLogTrace( wxT("widget"), wxT("XWindow 0x%08x <-> window %p (%s)"),
+                (unsigned int) w, win, win->GetClassInfo()->GetClassName());
 
     return TRUE;
 }
@@ -1291,15 +1344,15 @@ 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());
+        wxLogDebug( wxT("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());
+    wxLogTrace( wxT("widget"), wxT("XWindow 0x%08x <-> window %p (%s)"),
+                (unsigned int) w, win, win->GetClassInfo()->GetClassName());
 
     return TRUE;
 }
@@ -1327,7 +1380,7 @@ WXWindow wxWindowX11::GetMainWindow() const
     return m_mainWindow;
 }
 
-WXWindow wxWindowX11::GetClientWindow() const
+WXWindow wxWindowX11::GetClientAreaWindow() const
 {
     return m_clientWindow;
 }
@@ -1461,7 +1514,7 @@ bool wxTranslateMouseEvent(wxMouseEvent& wxevent, wxWindow *win, Window window,
     return FALSE;
 }
 
-bool wxTranslateKeyEvent(wxKeyEvent& wxevent, wxWindow *win, Window WXUNUSED(win), XEvent *xevent)
+bool wxTranslateKeyEvent(wxKeyEvent& wxevent, wxWindow *win, Window WXUNUSED(win), XEvent *xevent, bool isAscii)
 {
     switch (XEventGetType(xevent))
     {
@@ -1473,6 +1526,14 @@ bool wxTranslateKeyEvent(wxKeyEvent& wxevent, wxWindow *win, Window WXUNUSED(win
             KeySym keySym;
             (void) XLookupString ((XKeyEvent *) xevent, buf, 20, &keySym, NULL);
             int id = wxCharCodeXToWX (keySym);
+            // id may be WXK_xxx code - these are outside ASCII range, so we
+            // can't just use toupper() on id.
+            // Only change this if we want the raw key that was pressed,
+            // and don't change it if we want an ASCII value.
+            if (!isAscii && (id >= 'a' && id <= 'z'))
+            {
+                id = id + 'A' - 'a';
+            }
 
             wxevent.m_shiftDown = XKeyEventShiftIsDown(xevent);
             wxevent.m_controlDown = XKeyEventCtrlIsDown(xevent);
@@ -1485,11 +1546,7 @@ bool wxTranslateKeyEvent(wxKeyEvent& wxevent, wxWindow *win, Window WXUNUSED(win
             wxevent.m_x = XKeyEventGetX(xevent);
             wxevent.m_y = XKeyEventGetY(xevent);
 
-            if (id > -1)
-                return TRUE;
-            else
-                return FALSE;
-            break;
+            return id > -1;
         }
     default:
         break;
@@ -1565,8 +1622,8 @@ wxPoint wxGetMousePosition()
     unsigned int maskReturn;
 
     XQueryPointer (display,
-                  rootWindow,
-                  &rootReturn,
+                   rootWindow,
+                   &rootReturn,
                    &childReturn,
                    &rootX, &rootY, &winX, &winY, &maskReturn);
     return wxPoint(rootX, rootY);