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() {
}
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)
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);
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); }
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);
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); }
// 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();
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 /////////////////////////////////////
/**
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());
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 /////////////////////////////////////////////////
/** 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;
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;
}
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); }
/** 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);
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);
if (dirt[j] != null)
dirtyRegions.dirty(dirt[j][0], dirt[j][1], dirt[j][2], dirt[j][3]);
- // tail-recurse
- render();
return;
}
}
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;
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);
}
}
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);
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);
}