2002/08/07 04:42:00
[org.ibex.core.git] / src / org / xwt / plat / POSIX.java
index f331f9a..e47cc9b 100644 (file)
@@ -1,15 +1,6 @@
 // Copyright 2002 Adam Megacz, see the COPYING file for licensing [LGPL]
 package org.xwt.plat;
 
-// FIXME: protected void _newBrowserWindow(String url)
-// FIXME: When should I use RootWindow versus DefaultRootWindow?
-// FIXME: Solaris: xwt.altKeyName -> "Meta"
-// FIXME: minimize/taskbar icon
-// FIXME: 15bpp? can't assume depth/8 == bytespp
-// FIXME: check for x resource / memory leaks
-// FIXME: WM_HINTS flags: icon pixmap, icon window [[ have to wait until we have gnome/kde wm's installed ]]
-// FIXME: code-review POSIX.cc
-
 import java.awt.*;
 import java.awt.image.*;
 import gnu.gcj.RawData;
@@ -43,6 +34,7 @@ public class POSIX extends GCJ {
 
     // General Methods ///////////////////////////////////////////////////////
 
+    protected String _getAltKeyName() { return System.getProperty("os.name", "").indexOf("SunOS") != -1 ? "Meta" : "Alt"; }
     protected String[] _listFonts() { return fontList; }
     protected String getDescriptiveName() { return "GCJ Linux Binary"; }
     protected Picture _createPicture(int[] data, int w, int h) { return new POSIX.X11Picture(data, w, h); }
@@ -60,6 +52,34 @@ public class POSIX extends GCJ {
     protected native void eventThread();
     private native void natInit();
 
+    /** returns the value of the environment variable key, or null if no such key exists */
+    protected native String _getEnv(String key);
+    
+    /** spawns a process which is immune to SIGHUP */
+    private static native void spawnChildProcess(String[] command);
+
+    protected void _newBrowserWindow(String url) {
+        String browserString = getEnv("BROWSER");
+        if (browserString == null) {
+            browserString = "netscape " + url;
+        } else if (browserString.indexOf("%s") != -1) {
+            browserString =
+                browserString.substring(0, browserString.indexOf("%s")) +
+                url + browserString.substring(browserString.indexOf("%s") + 2);
+        } else {
+            browserString += " " + url;
+        }
+
+        StringTokenizer st = new StringTokenizer(browserString, " ");
+        String[] cmd = new String[st.countTokens()];
+        for(int i=0; st.hasMoreTokens(); i++) {
+            cmd[i] = st.nextToken();
+            System.out.println(i + ":" + cmd[i]);
+        }
+
+        spawnChildProcess(cmd);
+    }
+
     public POSIX() { }
     public void init() {
         natInit();
@@ -77,9 +97,9 @@ public class POSIX extends GCJ {
         boolean framed = false;
         Semaphore waitForCreation = new Semaphore();
         
-        public void setIcon(Picture p) { /* FIXME */ }
-        public void setInvisible(boolean i) { /* FIXME */ }
+        public native void setInvisible(boolean i);
         public void _setMaximized(boolean m) { if (Log.on) Log.log(this, "POSIX/X11 can't maximize windows"); }
+        public native void setIcon(Picture p);
         public native void _setMinimized(boolean b);
         public native void setTitleBarText(String s);
         public native void setSize(int w, int h);
@@ -104,9 +124,13 @@ public class POSIX extends GCJ {
 
     // Our Subclass of Picture ///////////////////////////////////////////////
 
-    // FIXME: what if display server runs out of pixmap space? Think resource conservation...
-
-    /** Implements a Picture as an X11 Pixmap */
+    /**
+     *  Implements a Picture. No special X11 structure is created
+     *  unless the image has no alpha (in which case a
+     *  non-shared-pixmap DoubleBuffer is created), or all-or-nothing
+     *  alpha (in which case a non-shared-pixmap DoubleBuffer with a
+     *  stipple bitmap is created).
+     */
     public static class X11Picture implements Picture {
         
         int width;
@@ -121,21 +145,36 @@ public class POSIX extends GCJ {
             this.data = data;
             this.width = w;
             this.height = h;
+            boolean needsStipple = false;
 
             // if we have any non-0x00, non-0xFF alphas, we can't double buffer ourselves
             for(int i=0; i<w*h; i++)
-                if ((data[i] & 0xFF000000) != 0xFF000000 && (data[i] & 0xFF000000) != 0x00)
+                if ((data[i] & 0xFF000000) == 0xFF000000)
+                    needsStipple = true;
+                else if ((data[i] & 0xFF000000) != 0x00)
                     return;
 
-            X11DoubleBuffer b = new X11DoubleBuffer(w, h);
+            buildDoubleBuffer(needsStipple);
+        }
+
+        void buildDoubleBuffer(boolean needsStipple) {
+            if (doublebuf != null) return;
+            // no point in using a shared pixmap since we'll only write to this image once
+            X11DoubleBuffer b = new X11DoubleBuffer(width, height, false);
             b.drawPicture(this, 0, 0);
-            b.createStipple(this);
+            if (needsStipple) b.createStipple(this);
             doublebuf = b;
         }
 
     }
 
-    // FIXME: finalizer to free X resources
+    /**
+     *  An X11DoubleBuffer is implemented as an X11 pixmap. "Normal"
+     *  DoubleBuffers will use XShm shared pixmaps if
+     *  available. X11DoubleBuffers created to accelerate Pictures
+     *  with all-or-nothing alpha will not use shared pixmaps, however
+     *  (since they are only written to once.
+     */
     public static class X11DoubleBuffer implements DoubleBuffer {
 
         int clipx, clipy, clipw, cliph;
@@ -147,31 +186,22 @@ public class POSIX extends GCJ {
 
         /** Sets the DoubleBuffer's internal stipple to the alpha==0x00 regions of xpi */
         public native void createStipple(X11Picture xpi);
-
-        static int old_shmsize = 0;
-        static RawData shm_ximage;
-        static int shmsegs = 0;
-        int force_slowpath = 0;
-        RawData mxi = null;
-        int shared_pixmap = 0;
-
-        boolean usePixmap = false;
         
-        /** Pixmap (if any) representing this Picture */
-        RawData pm;
-
-        /** Graphics Context on pm (never changes, so it's fast) */
-        RawData gc;
+        RawData pm;                    // Pixmap (if any) representing this Picture
+        boolean shared_pixmap = false; // true if pm is a ShmPixmap
+        RawData fake_ximage = null;    // a 'fake' XImage corresponding to the shared pixmap; gives us the address and depth parameters
+        RawData shm_segment = null;    // XShmSegmentInfo
 
-        /** Graphics Context on pm, use this one if you need a clip/stipple */
-        RawData clipped_gc;
+        RawData gc;                    // Graphics Context on pm (never changes, so it's fast)
+        RawData clipped_gc;            // Graphics Context on pm, use this one if you need a clip/stipple
 
         /** DoubleBuffer mode */
-        public X11DoubleBuffer(int w, int h) {
+        public X11DoubleBuffer(int w, int h) { this(w, h, true); }
+        public X11DoubleBuffer(int w, int h, boolean shared_pixmap) {
             width = clipw = w;
             height = cliph = h;
             clipx = clipy = 0;
-            shared_pixmap = 1;
+            this.shared_pixmap = shared_pixmap;
             natInit();
         }
 
@@ -186,12 +216,25 @@ public class POSIX extends GCJ {
             drawPicture(source, x, y, x + source.getWidth(), y + source.getHeight(), 0, 0, source.getWidth(), source.getHeight());
         }
 
+        public void drawPicture(Picture source, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2) {
+            if (!(dx2 - dx1 != sx2 - sx1 || dy2 - dy1 != sy2 - sy1) && ((X11Picture)source).doublebuf != null)
+                fastDrawPicture(source, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2);
+            else 
+                slowDrawPicture(source, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2);
+        }
+
+        /** fast path for image drawing (no scaling, all-or-nothing alpha) */
+        public native void fastDrawPicture(Picture source, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2);
+
+        /** slow path for image drawing */
+        public native void slowDrawPicture(Picture source, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2);
+
         public int getWidth() { return width; }
         public int getHeight() { return height; }
         public native void natInit();
-        public native void drawPicture(Picture source, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2);
         public native void fillRect(int x, int y, int x2, int y2, int color);
         public native void drawString(String font, String text, int x, int y, int color);
+        public native void finalize();
 
     }
 
@@ -213,19 +256,35 @@ public class POSIX extends GCJ {
     public void initFonts() {
         // use the font list to build nativeFontList
         String[] fonts = listNativeFonts();
+
+        Vector v = new Vector();
         for(int k=0; k<fonts.length; k++) {
+
             String s = fonts[k].toLowerCase();
-            StringTokenizer st = new StringTokenizer(s, "-", false);
-            String[] font = new String[st.countTokens()];
-            
+            String s2 = s;
             try {
-                for(int i=0; st.hasMoreTokens(); i++) font[i] = st.nextToken();
+                v.setSize(0);
+                s = s.substring(s.indexOf('-') + 1);
+                while (s.indexOf('-') != -1) {
+                    v.addElement(s.substring(0, s.indexOf('-')));
+                    s = s.substring(s.indexOf('-') + 1);
+                }
+                v.addElement(s);
+                String[] font = new String[v.size()];
+                v.copyInto(font);
+
+                // limit to iso8559 until we can do I18N properly....
+                if (font.length > 12) {
+                    if (!font[12].equals("iso8859") && !font[12].equals("")) continue;
+                    if (font.length < 14 || !font[13].equals("1")) continue;
+                }
+
                 String name = font[1];
                 String size = font[6];
-                String slant = font[3].equals("i") ? "i" : "";
+                String slant = (font[3].equals("i") || font[3].equals("o")) ? "i" : "";
                 String bold = font[2].equals("bold") ? "b" : "";
-                String tail = s.substring(1 + font[0].length() + 1 + font[1].length() + 1 + font[2].length() + 1 +
-                                          font[3].length() + 1 + font[4].length() + 1);
+                String tail = s2.substring(1 + font[0].length() + 1 + font[1].length() + 1 + font[2].length() + 1 +
+                                           font[3].length() + 1 + font[4].length() + 1);
                 
                 if (bold.equals("*") && slant.equals("*")) {
                     nativeFontList.put(name + size, font[0] + "-" + font[1] + "-regular-r-" + font[4] + "-" + tail);
@@ -242,11 +301,11 @@ public class POSIX extends GCJ {
                     nativeFontList.put(name + size + bold + "i", font[0] + "-" + font[1] + "-" + font[2] + "-i-" + font[4] + "-" + tail);
                     
                 } else {
-                    nativeFontList.put(name + size + bold + slant, s);
+                    nativeFontList.put(name + size + bold + slant, s2);
                     
                 }
             } catch (ArrayIndexOutOfBoundsException e) {
-                if (Log.on) Log.log(this, "skipping incomplete font string " + s);
+                if (Log.on) Log.log(this, "skipping incomplete font string " + s2);
                 continue;
             }
         }
@@ -310,6 +369,7 @@ public class POSIX extends GCJ {
             for(int j=0; j<6; j++) i = target.indexOf('-', i + 1);
             target = target.substring(0, i + 1) + arg.size + target.substring(target.indexOf('-', i+1));
         }
+        if (Log.on) Log.log(POSIX.class, "mapping font \"" + s + "\" to \"" + target + "\"");
         RawData ret = fontStringToStruct(target);
         if (ret == null) ret = fontStringToStruct("fixed");
         xwtFontToFontStruct.put(s, new WrappedRawData(ret));