2003/12/22 04:50:08
authormegacz <megacz@xwt.org>
Fri, 30 Jan 2004 07:43:07 +0000 (07:43 +0000)
committermegacz <megacz@xwt.org>
Fri, 30 Jan 2004 07:43:07 +0000 (07:43 +0000)
darcs-hash:20040130074307-2ba56-7bbae5c3d483cf4adc7a83a739912b81d8353c88.gz

src/org/xwt/Box.java
src/org/xwt/Platform.java
src/org/xwt/Scheduler.java
src/org/xwt/Surface.java
src/org/xwt/plat/AWT.java

index 6b90368..98fb49e 100644 (file)
@@ -255,15 +255,28 @@ public final class Box extends JSScope implements Scheduler.Task {
     void resize(LENGTH x, LENGTH y, LENGTH width, LENGTH height) {
         // FEATURE reimplement, but we're destroying this
         // FIXME: uncommenting this breaks; see http://bugs.xwt.org/show_bug.cgi?id=345
-        //if (x != this.x || y != this.y || width != this.width || height != this.height) {
-            (parent == null ? this : parent).dirty(this.x, this.y, this.width, this.height);
+        if (x != this.x || y != this.y || width != this.width || height != this.height) {
             boolean sizechange = (this.width != width || this.height != height) && getTrap("SizeChange") != null;
             boolean poschange = (this.x != x || this.y != y) && getTrap("PosChange") != null;
+            do {
+                if (texture == null && (text == null || text.equals(""))) {
+                    if ((fillcolor & 0xff000000) == 0) break;
+                    // FEATURE: more optimizations here
+                    if (this.x == x && this.y == y) {
+                        Box who = (parent == null ? this : parent);
+                        who.dirty(min(this.x+this.width,x+width), y, Math.abs(width-this.width), max(this.height, height));
+                        who.dirty(x, min(this.y+this.height,y+height), max(this.width, width), Math.abs(height-this.height));
+                        break;
+                    }
+                }
+                (parent == null ? this : parent).dirty(this.x, this.y, this.width, this.height);
+                this.width = width; this.height = height; this.x = x; this.y = y;
+                dirty();
+            } while (false);
             this.width = width; this.height = height; this.x = x; this.y = y;
-            dirty();
             if (sizechange) putAndTriggerTrapsAndCatchExceptions("SizeChange", T);
             if (poschange)  putAndTriggerTrapsAndCatchExceptions("PosChange", T);
-            //}
+        }
     }
 
     void resize_children() {
@@ -349,7 +362,7 @@ public final class Box extends JSScope implements Scheduler.Task {
         }
 
         if ((fillcolor & 0xFF000000) != 0x00000000)
-            buf.fillTrapezoid(globalx, globalx + width, globaly, globalx, globalx + width, globaly + height, fillcolor);
+            buf.fillTrapezoid(cx1, cx2, cy1, cx1, cx2, cy2, fillcolor);
 
         // FIXME: do aspect in here
         if (texture != null && texture.isLoaded)
@@ -431,9 +444,11 @@ public final class Box extends JSScope implements Scheduler.Task {
         case "globalx": return N(localToGlobalX(0));
         case "globaly": return N(localToGlobalY(0));
         case "cursor": return test(CURSOR) ? boxToCursor.get(this) : null;
-        case "mousex": { Surface s = getSurface(); return N(s == null ? 0 : globalToLocalX(s.mousex)); }
-        case "mousey": { Surface s = getSurface(); return N(s == null ? 0 : globalToLocalY(s.mousey)); }
-        case "mouseinside": return B(test(MOUSEINSIDE));
+        case "mouse":
+            if (getSurface() == null) return null;
+            if (getSurface()._mousex == Integer.MAX_VALUE)
+                throw new JSExn("you cannot read from the box.mouse property in background thread context");
+            return new Mouse();
         case "numchildren": return redirect == null ? N(0) : redirect == this ? N(treeSize()) : redirect.get("numchildren");
         case "minwidth": return N(minwidth);
         case "maxwidth": return N(maxwidth);
@@ -446,6 +461,19 @@ public final class Box extends JSScope implements Scheduler.Task {
         throw new Error("unreachable"); // unreachable
     }
 
+    private class Mouse extends JS {
+        public Object get(Object key) {
+            //#switch(key)
+            case "x": return N(globalToLocalX(getSurface()._mousex));
+            case "y": return N(globalToLocalY(getSurface()._mousey));
+
+            // this might not get recomputed if we change mousex/mousey...
+            case "inside": return B(MOUSEINSIDE);
+            //#end
+            return null;
+        }
+    }
+
     void setMaxWidth(Object value) { do { CHECKSET_INT(maxwidth); MARK_RESIZE; } while(false); }
     void setMaxHeight(Object value) { do { CHECKSET_INT(maxheight); MARK_RESIZE; } while(false); }
 
@@ -479,6 +507,11 @@ public final class Box extends JSScope implements Scheduler.Task {
         case "align": clear(ALIGNS); setAlign(value == null ? "center" : value); MARK_RESIZE;
         case "cursor": setCursor(value);
         case "fill": setFill(value);
+        case "mouse":
+            int mousex = toInt(((JS)value).get("x"));
+            int mousey = toInt(((JS)value).get("y"));
+            getSurface()._mousex = localToGlobalX(mousex);
+            getSurface()._mousey = localToGlobalY(mousey);
         case "Minimized": if (parent == null && getSurface() != null) getSurface().minimized = toBoolean(value);  // FEATURE
         case "Maximized": if (parent == null && getSurface() != null) getSurface().maximized = toBoolean(value);  // FEATURE
         case "Close": if (parent == null && getSurface() != null) getSurface().dispose(true);
@@ -600,8 +633,8 @@ public final class Box extends JSScope implements Scheduler.Task {
 
         String name = (String)name_;
         if (getSurface() == null) return;
-        int x = globalToLocalX(getSurface().mousex);
-        int y = globalToLocalY(getSurface().mousey);
+        int x = globalToLocalX(getSurface()._mousex);
+        int y = globalToLocalY(getSurface()._mousey);
         boolean wasinside = test(MOUSEINSIDE);
         boolean isinside = test(VISIBLE) && inside(x, y) && !obscured;
         if (!wasinside && isinside) { set(MOUSEINSIDE);   putAndTriggerTrapsAndCatchExceptions("Enter", T); }
index 45e303c..d3b0c19 100644 (file)
@@ -56,7 +56,7 @@ public abstract class Platform {
 
             // Disable 2d hardware acceleration on Jaguar (do we need this?)
             // if (os_name.equals("Mac OS X") && os_version.startsWith("10.2")) System.setProperty("com.apple.hwaccel", "false");
-            // System.setProperty("com.apple.hwaccel", "true");
+            //System.setProperty("com.apple.hwaccel", "false");
 
             if (platform_class != null)
                 Class.forName("org.xwt.plat." + platform_class).newInstance();
index 5000287..55be6df 100644 (file)
@@ -23,6 +23,9 @@ public class Scheduler {
 
     public static void init() { if (singleton == null) (singleton = Platform.getScheduler()).run(); }
 
+    private static Task current = null;
+    public static Task current() { return current; }
+
     // API which must be supported by subclasses /////////////////////////////////////
 
     /**
@@ -40,12 +43,20 @@ public class Scheduler {
     protected static Queue runnable = new Queue(50);
     public void defaultRun() {
         while(true) {
-            Task t = (Task)runnable.remove(true);
+            current = (Task)runnable.remove(true);
             try {
-                t.perform();
-                // FEATURE: be smarter about this
-                //if (t != Surface.renderAll) add(Surface.renderAll);
-                Surface.renderAll.perform();
+                for(int i=0; i<Surface.allSurfaces.size(); i++) {
+                    Surface s = (Surface)Surface.allSurfaces.elementAt(i);
+                    if (current instanceof JSFunction) {
+                        s._mousex = Integer.MAX_VALUE;
+                        s._mousey = Integer.MAX_VALUE;
+                    } else {
+                        s._mousex = s.mousex;
+                        s._mousey = s.mousey;
+                    }
+                }
+                current.perform();
+                if (runnable.size() == 0 && Surface.needRender) Surface.renderAll.perform();
             } catch (JSExn e) {
                 Log.log(Scheduler.class, "a JavaScript thread spawned with xwt.thread() threw an exception:");
                 Log.log(Scheduler.class, e.toString());
index fe5844f..eca0dee 100644 (file)
@@ -46,11 +46,13 @@ public abstract class Surface extends PixelBuffer implements Scheduler.Task {
     public String cursor = "default";                  ///< The active cursor to switch to when syncCursor() is called
     public int mousex;                                 ///< x position of the mouse, in Scheduler-time
     public int mousey;                                 ///< y position of the mouse, in Scheduler-time
+    public int _mousex;                                ///< x position of the mouse, in Scheduler-time
+    public int _mousey;                                ///< y position of the mouse, in Scheduler-time
     public int newmousex = -1;                         ///< x position of the mouse, in realtime
     public int newmousey = -1;                         ///< y position of the mouse, in realtime
     public boolean minimized = false;                  ///< True iff this surface is minimized, in real time
     public boolean maximized = false;                  ///< True iff this surface is maximized, in real time
-    private DirtyList dirtyRegions = new DirtyList();  ///< Dirty regions on the *screen*
+    DirtyList dirtyRegions = new DirtyList();  ///< Dirty regions on the *screen*
 
     // Used For Simulating Clicks and DoubleClicks /////////////////////////////////////////////////
 
@@ -129,7 +131,6 @@ public abstract class Surface extends PixelBuffer implements Scheduler.Task {
 
     /** we enqueue ourselves in the Scheduler when we have a Move message to deal with */
     public void perform() {
-        inqueue = false;
         if (mousex == newmousex && mousey == newmousey) return;
         int oldmousex = mousex;     mousex = newmousex;
         int oldmousey = mousey;     mousey = newmousey;
@@ -154,30 +155,24 @@ public abstract class Surface extends PixelBuffer implements Scheduler.Task {
     protected final void Move(final int newmousex, final int newmousey) {
         this.newmousex = newmousex;
         this.newmousey = newmousey;
-        if (!inqueue) Scheduler.add(this);
-        inqueue = true;
+        Scheduler.add(this);
     }
-    boolean inqueue = false;
 
-    Scheduler.Task nextSizeChange = null;
-    int nextWidth = 0;
-    int nextHeight = 0;
+    private Scheduler.Task nextSizeChange = null;
     // FEATURE: can we avoid creating objects here?
     /** subclasses should invoke this method when the user resizes the window */
     protected final void SizeChange(final int width, final int height) {
-        nextWidth = width;
-        nextHeight = height;
-        if (nextSizeChange != null) return;
         if (root.maxwidth == width && root.maxheight == height) return;
         nextSizeChange = new Scheduler.Task() { public void perform() {
             if (nextSizeChange != this) return;
             // dirty the place where the scar used to be
             root.dirty(0, root.maxheight - Main.scarImage.height, Main.scarImage.width, Main.scarImage.height);
-            root.setMaxWidth(JS.N(nextWidth));
-            root.setMaxHeight(JS.N(nextHeight));
+            root.setMaxWidth(JS.N(width));
+            root.setMaxHeight(JS.N(height));
             nextSizeChange = null;
+            Refresh();
         }};
-        Scheduler.add(nextSizeChange);
+        Scheduler.addAtFront(nextSizeChange);
         abort = true;
     }
 
@@ -198,12 +193,19 @@ public abstract class Surface extends PixelBuffer implements Scheduler.Task {
     protected final void Minimized(boolean b) { minimized = b; new SimpleMessage("Minimized", b ? T : F, root); }
     protected final void Maximized(boolean b) { maximized = b; new SimpleMessage("Maximized", b ? T : F, root); }
     protected final void Focused(boolean b) { new SimpleMessage("Focused", b ? T : F, root); }
-    public static void Refresh() { /*Scheduler.add(renderAll);*/ }
-
-    public static final Scheduler.Task renderAll = new Scheduler.Task() { public void perform() {
-        for(int i=0; i<allSurfaces.size(); i++)
-            ((Surface)allSurfaces.elementAt(i)).render();
-    } };
+    public static void Refresh() { needRender = true; Scheduler.add(new Scheduler.Task() { public void perform() { } }); }
+
+    public static boolean needRender = false;
+    public static final Scheduler.Task renderAll = new Scheduler.Task() {
+            public void perform() {
+                for(int i=0; i<allSurfaces.size(); i++) {
+                    Surface s = ((Surface)allSurfaces.elementAt(i));
+                    do {
+                        s.render(); 
+                    } while(s.abort);
+                }
+            }
+        };
 
     public final void setMaximized(boolean b) { if (b != maximized) _setMaximized(maximized = b); }
     public final void setMinimized(boolean b) { if (b != minimized) _setMinimized(minimized = b); }
@@ -249,7 +251,6 @@ public abstract class Surface extends PixelBuffer implements Scheduler.Task {
 
     /** runs the prerender() and render() pipelines in the root Box to regenerate the backbuffer, then blits it to the screen */
     public synchronized void render() {
-
         // dirty the place where the scar used to be in case the root window size was programmatically changed
         if (root.maxwidth != root.width || root.maxheight != root.height)
             root.dirty(0, root.height - Main.scarImage.height, Main.scarImage.width, Main.scarImage.height);
@@ -260,7 +261,7 @@ public abstract class Surface extends PixelBuffer implements Scheduler.Task {
             root.repack();
             root.resize(root.x, root.y, root.maxwidth, root.maxheight);
             root.resize_children();
-            //_setSize(root.width, root.height);
+            _setSize(root.width, root.height);
             String oldcursor = cursor;
             cursor = "default";
             root.putAndTriggerTrapsAndCatchExceptions("_Move", JS.T);
@@ -290,8 +291,6 @@ public abstract class Surface extends PixelBuffer implements Scheduler.Task {
                     if (dirt[j] != null)
                         dirtyRegions.dirty(dirt[j][0], dirt[j][1], dirt[j][2], dirt[j][3]);
 
-                // tail-recurse
-                render();
                 return;
             }
         }
@@ -361,13 +360,10 @@ public abstract class Surface extends PixelBuffer implements Scheduler.Task {
             backbuffer.fillTrapezoid(x1, x2, y1, x3, x4, y2, color);
         }
 
+        public void render_() { render(); }
         public void render() {
-            Dirty(0, 0, root.width, root.height);
             super.render();
-            render_();
-        }
-
-        public void render_() {
+            if (abort) return;
             int[][] dirt = screenDirtyRegions.flush();
             for(int i = 0; dirt != null && i < dirt.length; i++) {
                 if (dirt[i] == null) continue;
@@ -380,6 +376,7 @@ public abstract class Surface extends PixelBuffer implements Scheduler.Task {
                 if (x+w > root.width) w = root.width - x;
                 if (y+h > root.height) h = root.height - y;
                 if (w <= 0 || h <= 0) continue;
+                if (abort) return;
                 blit(backbuffer, x, y, x, y, w + x, h + y);
             }
         }
@@ -390,6 +387,11 @@ public abstract class Surface extends PixelBuffer implements Scheduler.Task {
             Refresh();
         }
 
+        public void dirty(int x, int y, int w, int h) {
+            screenDirtyRegions.dirty(x, y, w, h);
+            super.dirty(x, y, w, h);
+        }
+
         /** copies a region from the doublebuffer to this surface */
         public abstract void blit(PixelBuffer source, int sx, int sy, int dx, int dy, int dx2, int dy2);
 
index 0951f8f..44c43f0 100644 (file)
@@ -290,7 +290,8 @@ public class AWT extends JVM {
                 int newwidth = Math.max(r.x - insets.left + r.width, root.width);
                 int newheight = Math.max(r.y - insets.top + r.height, root.height);
                 if (newwidth > root.width || newheight > root.height)
-                    componentResized(window.getWidth() - insets.left - insets.right, window.getHeight() - insets.top - insets.bottom);
+                    componentResized(window.getWidth() - insets.left - insets.right,
+                                     window.getHeight() - insets.top - insets.bottom);
 
                 Dirty(r.x - insets.left, r.y - insets.top, r.width, r.height);
             }