Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Changing a CALayer in a menu callback doesn't trigger re-draw #2018

Open
wants to merge 2 commits into from

4 participants

@zittix

If in a menu action we change some properties of a CALayer such as:


var af = CGAffineTransformMakeScale(scale/100.0,scale/100.0);
[myLayer setAffineTransform:af];

The update is not applied to the layer until the mouse is moved (tested on Safari 7.0 and Chrome 31.0).

The provided fix force the update of the CALayer tree at the end of the menu callback.

@cappbot
Collaborator

Milestone: Someday. Label: #new. What's next? A reviewer should examine this issue.

@aljungberg
Owner

Doesn't CALayer do a perform on runloop for that [CALayer runLoopUpdateLayers], and that's why the update does happen once the mouse moves?

So it seems the real problem is that the run loop doesn't enter a second iteration here. Probably we got to this point via a non-run-loop path and the comment nearby seems to describe a similar problem.

So, maybe what we should actually be doing instead of adding more layers of custom calls is to just pump the run loop or schedule an immediate timer.

Did you trace this behaviour by any chance?

+bug
+AppKit
+#needs-test

@cappbot
Collaborator

Milestone: Someday. Labels: #new, AppKit, bug. What's next? A reviewer should examine this issue.

@ahankinson

-#new

@cappbot
Collaborator

Milestone: Someday. Labels: AppKit, bug. What's next? A reviewer should examine this issue.

@cappbot
Collaborator

Milestone: Someday. Labels: #needs-unit-test, AppKit, bug. What's next? This issue needs a volunteer to write and submit one or more unit tests execercising the changes and/or the relevant parts of the original problem.

@zittix

The unit tests have been added.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Nov 18, 2013
  1. @zittix
Commits on Dec 19, 2014
  1. @zittix
This page is out of date. Refresh to see the latest.
View
5 AppKit/CPMenu/CPMenu.j
@@ -27,6 +27,7 @@
@import "CPKeyValueBinding.j"
@import "CPMenuItem.j"
+@import "CALayer.j"
@global CPApp
@@ -999,6 +1000,10 @@ var _CPMenuBarVisible = NO,
// an additional mouse move after all this, but not in other browsers.
// This will be fixed correctly with the coming run loop changes.
[_CPDisplayServer run];
+
+ // If layers are updated within the menu callback, the re-draw & re-layout doesn't occur until a mouse move.
+ // We force the update here.
+ [CALayer runLoopUpdateLayers];
}
/* @ignore */
View
75 Tests/Manual/CPMenuCALayerTest/AppController.j
@@ -0,0 +1,75 @@
+/*
+ * AppController.j
+ * CPMenuCALayerTest
+ *
+ * Created by Mathieu Monney on December 19, 2014.
+ * Copyright 2014, Vidinoti SA, All rights reserved.
+ */
+
+@import <Foundation/CPObject.j>
+
+@implementation MyLayer : CALayer
+{
+}
+
+- (void)drawInContext:(CGContext)aContext {
+ CGContextSetFillColor(aContext, [CPColor blackColor]);
+ CGContextFillRect(aContext, _bounds);
+}
+
+@end
+
+@implementation AppController : CPObject
+{
+ MyLayer layer;
+}
+
+-(void)changeSize:(id)sender {
+ var scale = [[sender selectedItem] title];
+ scale = scale.substr(0,scale.length-1);
+
+ // Change the affine transform of the layer to make sure it is updated due to
+ // https://github.com/cappuccino/cappuccino/pull/2018
+ var af = CGAffineTransformMakeScale(scale/100.0,scale/100.0);
+ [layer setAffineTransform:af];
+}
+
+- (void)applicationDidFinishLaunching:(CPNotification)aNotification
+{
+ var theWindow = [[CPWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:CPBorderlessBridgeWindowMask],
+ contentView = [theWindow contentView],
+ popupButton = [[CPPopUpButton alloc] initWithFrame:CGRectMakeZero()];
+
+ // Changing the button should change the size of the layer if #2018 is fixed.
+ [popupButton addItemsWithTitles:[@"100%",@"50%",@"25%"]];
+ [popupButton sizeToFit];
+ [popupButton setAction:@selector(changeSize:)];
+ [popupButton setTarget:self];
+
+ [popupButton setAutoresizingMask:CPViewMinXMargin | CPViewMaxXMargin | CPViewMinYMargin | CPViewMaxYMargin];
+ [popupButton setCenter:[contentView center]];
+
+ [contentView addSubview:popupButton];
+
+ [theWindow orderFront:self];
+
+ var layerRoot = [[CALayer alloc ] init];
+ [layerRoot setBounds:CGRectMake(0,0,[contentView bounds].size.width,[contentView bounds].size.height)];
+ [layerRoot setPosition:CGPointMake(0,0)];
+ [contentView setWantsLayer:YES];
+
+ [contentView setLayer:layerRoot];
+
+ layer = [[MyLayer alloc ] init];
+ [layer setBounds:CGRectMake(0,0,100,100)];
+ [layer setPosition:CGPointMake([contentView bounds].size.width/2,[contentView bounds].size.height/2-100)];
+ [layer setNeedsDisplay];
+
+ [layerRoot addSublayer:layer];
+
+ // Uncomment the following line to turn on the standard menu bar.
+ //[CPMenu setMenuBarVisible:YES];
+}
+
+
+@end
View
12 Tests/Manual/CPMenuCALayerTest/Info.plist
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CPApplicationDelegateClass</key>
+ <string>AppController</string>
+ <key>CPBundleName</key>
+ <string>CPMenuCALayerTest</string>
+ <key>CPPrincipalClass</key>
+ <string>CPApplication</string>
+</dict>
+</plist>
View
93 Tests/Manual/CPMenuCALayerTest/Jakefile
@@ -0,0 +1,93 @@
+/*
+ * Jakefile
+ * CPMenuCALayerTest
+ *
+ * Created by Mathieu Monney on December 19, 2014.
+ * Copyright 2014, Vidinoti SA, All rights reserved.
+ */
+
+var ENV = require("system").env,
+ FILE = require("file"),
+ JAKE = require("jake"),
+ task = JAKE.task,
+ FileList = JAKE.FileList,
+ app = require("cappuccino/jake").app,
+ configuration = ENV["CONFIG"] || ENV["CONFIGURATION"] || ENV["c"] || "Debug",
+ OS = require("os");
+
+app ("CPMenuCALayerTest", function(task)
+{
+ task.setBuildIntermediatesPath(FILE.join("Build", "CPMenuCALayerTest.build", configuration));
+ task.setBuildPath(FILE.join("Build", configuration));
+
+ task.setProductName("CPMenuCALayerTest");
+ task.setIdentifier("com.yourcompany.CPMenuCALayerTest");
+ task.setVersion("1.0");
+ task.setAuthor("WireLoad, LLC");
+ task.setEmail("feedback @nospam@ yourcompany.com");
+ task.setSummary("CPMenuCALayerTest");
+ task.setSources((new FileList("**/*.j")).exclude(FILE.join("Build", "**")));
+ task.setResources(new FileList("Resources/**"));
+ task.setIndexFilePath("index.html");
+ task.setInfoPlistPath("Info.plist");
+
+ if (configuration === "Debug")
+ task.setCompilerFlags("-DDEBUG -g");
+ else
+ task.setCompilerFlags("-O");
+});
+
+task ("default", ["CPMenuCALayerTest"], function()
+{
+ printResults(configuration);
+});
+
+task ("build", ["default"]);
+
+task ("debug", function()
+{
+ ENV["CONFIGURATION"] = "Debug";
+ JAKE.subjake(["."], "build", ENV);
+});
+
+task ("release", function()
+{
+ ENV["CONFIGURATION"] = "Release";
+ JAKE.subjake(["."], "build", ENV);
+});
+
+task ("run", ["debug"], function()
+{
+ OS.system(["open", FILE.join("Build", "Debug", "CPMenuCALayerTest", "index.html")]);
+});
+
+task ("run-release", ["release"], function()
+{
+ OS.system(["open", FILE.join("Build", "Release", "CPMenuCALayerTest", "index.html")]);
+});
+
+task ("deploy", ["release"], function()
+{
+ FILE.mkdirs(FILE.join("Build", "Deployment", "CPMenuCALayerTest"));
+ OS.system(["press", "-f", FILE.join("Build", "Release", "CPMenuCALayerTest"), FILE.join("Build", "Deployment", "CPMenuCALayerTest")]);
+ printResults("Deployment")
+});
+
+task ("desktop", ["release"], function()
+{
+ FILE.mkdirs(FILE.join("Build", "Desktop", "CPMenuCALayerTest"));
+ require("cappuccino/nativehost").buildNativeHost(FILE.join("Build", "Release", "CPMenuCALayerTest"), FILE.join("Build", "Desktop", "CPMenuCALayerTest", "CPMenuCALayerTest.app"));
+ printResults("Desktop")
+});
+
+task ("run-desktop", ["desktop"], function()
+{
+ OS.system([FILE.join("Build", "Desktop", "CPMenuCALayerTest", "CPMenuCALayerTest.app", "Contents", "MacOS", "NativeHost"), "-i"]);
+});
+
+function printResults(configuration)
+{
+ print("----------------------------");
+ print(configuration+" app built at path: "+FILE.join("Build", configuration, "CPMenuCALayerTest"));
+ print("----------------------------");
+}
View
BIN  Tests/Manual/CPMenuCALayerTest/Resources/spinner.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
103 Tests/Manual/CPMenuCALayerTest/index-debug.html
@@ -0,0 +1,103 @@
+<!DOCTYPE html
+ PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<!--
+ index-debug.html
+ CPMenuCALayerTest
+
+ Created by Mathieu Monney on December 19, 2014.
+ Copyright 2014, Vidinoti SA, All rights reserved.
+-->
+ <head>
+ <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7, chrome=1" />
+
+ <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
+
+ <meta name="apple-mobile-web-app-capable" content="yes" />
+ <meta name="apple-mobile-web-app-status-bar-style" content="black" />
+
+ <link rel="apple-touch-icon" href="Resources/icon.png" />
+ <link rel="apple-touch-startup-image" href="Resources/default.png" />
+
+ <title>CPMenuCALayerTest</title>
+
+ <script type="text/javascript">
+ OBJJ_MAIN_FILE = "main.j";
+ OBJJ_INCLUDE_PATHS = ["Frameworks/Debug", "Frameworks", "SomethingElse"];
+ </script>
+
+ <script src="Frameworks/Debug/Objective-J/Objective-J.js" type="text/javascript" charset="UTF-8"></script>
+
+ <script type="text/javascript">
+ objj_msgSend_reset();
+
+ // DEBUG OPTIONS:
+
+ // Uncomment to enable printing of backtraces on exceptions:
+ //objj_msgSend_decorate(objj_backtrace_decorator);
+
+ // Uncomment to supress exceptions that take place inside a message
+ //objj_msgSend_decorate(objj_supress_exceptions_decorator)
+
+ // Uncomment to enable runtime type checking:
+ //objj_msgSend_decorate(objj_typecheck_decorator);
+
+ // Uncomment (along with both above) to print backtraces on type check errors:
+ //objj_typecheck_prints_backtrace = true;
+
+ // Uncomment to disable the default logger (CPLogConsole if window.console exists, CPLogPopup otherwise):
+ //CPLogUnregister(CPLogDefault);
+
+ // Uncomment to enable a specific logger:
+ //CPLogRegister(CPLogConsole);
+ //CPLogRegister(CPLogPopup);
+ </script>
+
+ <style type="text/css">
+ body{margin:0; padding:0;}
+ #container {position: absolute; top:50%; left:50%;}
+ #content {width:800px; text-align:center; margin-left: -400px; height:50px; margin-top:-25px; line-height: 50px;}
+ #content {font-family: "Helvetica", "Arial", sans-serif; font-size: 18px; color: black; text-shadow: 0px 1px 0px white; }
+ #loadgraphic {margin-right: 0.2em; margin-bottom:-2px;}
+ </style>
+
+ <!--[if lt IE 7]>
+ <STYLE type="text/css">
+ #container { position: relative; top: 50%; }
+ #content { position: relative;}
+ </STYLE>
+ <![endif]-->
+
+ </head>
+
+ <body style="">
+ <div id="cappuccino-body">
+ <div id="loadingcontainer" style="background-color: #eeeeee; overflow:hidden; width:100%; height:100%; position: absolute; top: 0; left: 0;">
+ <script type="text/javascript">
+ document.write("<div id='container'><p id='content'>" +
+ "<img id='loadgraphic' width='16' height='16' src='Resources/spinner.gif' /> " +
+ "Loading CPMenuCALayerTest...</p></div>");
+ </script>
+
+ <noscript>
+ <div id="container">
+ <div style="width: 440px; padding: 10px 25px 20px 25px; font-family: sans-serif; background-color: #ffffff; position: relative; left: -245px; top: -120px; text-align: center; -moz-border-radius: 20px; -webkit-border-radius: 20px; color: #555555">
+ <p style="line-height: 1.4em;">JavaScript is required for this site to work correctly but is either disabled or not supported by your browser.</p>
+ <p style="font-size:120%; padding:10px;"><a href="http://cappuccino-project.org/noscript">Show me how to enable JavaScript</a></p>
+ <p style="font-size:80%;">You may want to upgrade to a newer browser while you're at it:</p>
+ <ul style="margin:0;padding:0; text-align: center; font-size:80%;" >
+ <li style="display: inline;"><a href="http://www.apple.com/safari/download/">Safari</a></li>
+ <li style="display: inline;"><a href="http://www.mozilla.com/en-US/firefox/">Firefox</a></li>
+ <li style="display: inline;"><a href="http://www.google.com/chrome/">Chrome</a></li>
+ <li style="display: inline;"><a href="http://www.opera.com/download/">Opera</a></li>
+ <li style="display: inline;"><a href="http://www.microsoft.com/windows/downloads/ie/getitnow.mspx">Internet Explorer</a></li>
+ </ul>
+ </div>
+ </div>
+ </noscript>
+ </div>
+ </div>
+ </body>
+
+</html>
View
78 Tests/Manual/CPMenuCALayerTest/index.html
@@ -0,0 +1,78 @@
+<!DOCTYPE html
+ PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<!--
+ index.html
+ CPMenuCALayerTest
+
+ Created by Mathieu Monney on December 19, 2014.
+ Copyright 2014, Vidinoti SA, All rights reserved.
+-->
+ <head>
+ <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7, chrome=1" />
+
+ <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
+
+ <meta name="apple-mobile-web-app-capable" content="yes" />
+ <meta name="apple-mobile-web-app-status-bar-style" content="black" />
+
+ <link rel="apple-touch-icon" href="Resources/icon.png" />
+ <link rel="apple-touch-startup-image" href="Resources/default.png" />
+
+ <title>CPMenuCALayerTest</title>
+
+ <script type="text/javascript">
+ OBJJ_MAIN_FILE = "main.j";
+ </script>
+
+ <script type="text/javascript" src="Frameworks/Objective-J/Objective-J.js" charset="UTF-8"></script>
+
+ <style type="text/css">
+ body{margin:0; padding:0;}
+ #container {position: absolute; top:50%; left:50%;}
+ #content {width:800px; text-align:center; margin-left: -400px; height:50px; margin-top:-25px; line-height: 50px;}
+ #content {font-family: "Helvetica", "Arial", sans-serif; font-size: 18px; color: black; text-shadow: 0px 1px 0px white; }
+ #loadgraphic {margin-right: 0.2em; margin-bottom:-2px;}
+ </style>
+
+ <!--[if lt IE 7]>
+ <STYLE type="text/css">
+ #container { position: relative; top: 50%; }
+ #content { position: relative;}
+ </STYLE>
+ <![endif]-->
+
+ </head>
+
+ <body style="">
+ <div id="cappuccino-body">
+ <div id="loadingcontainer" style="background-color: #eeeeee; overflow:hidden; width:100%; height:100%; position: absolute; top: 0; left: 0;">
+ <script type="text/javascript">
+ document.write("<div id='container'><p id='content'>" +
+ "<img id='loadgraphic' width='16' height='16' src='Resources/spinner.gif' /> " +
+ "Loading CPMenuCALayerTest...</p></div>");
+ </script>
+
+ <noscript>
+ <div id="container">
+ <div style="width: 440px; padding: 10px 25px 20px 25px; font-family: sans-serif; background-color: #ffffff; position: relative; left: -245px; top: -120px; text-align: center; -moz-border-radius: 20px; -webkit-border-radius: 20px; color: #555555">
+ <p style="line-height: 1.4em;">JavaScript is required for this site to work correctly but is either disabled or not supported by your browser.</p>
+ <p style="font-size:120%; padding:10px;"><a href="http://cappuccino-project.org/noscript">Show me how to enable JavaScript</a></p>
+ <p style="font-size:80%;">You may want to upgrade to a newer browser while you're at it:</p>
+ <ul style="margin:0;padding:0; text-align: center; font-size:80%;" >
+ <li style="display: inline;"><a href="http://www.apple.com/safari/download/">Safari</a></li>
+ <li style="display: inline;"><a href="http://www.mozilla.com/en-US/firefox/">Firefox</a></li>
+ <li style="display: inline;"><a href="http://www.google.com/chrome/">Chrome</a></li>
+ <li style="display: inline;"><a href="http://www.opera.com/download/">Opera</a></li>
+ <li style="display: inline;"><a href="http://www.microsoft.com/windows/downloads/ie/getitnow.mspx">Internet Explorer</a></li>
+ </ul>
+ </div>
+ </div>
+ </noscript>
+ </div>
+ </div>
+ </body>
+
+</html>
+
View
18 Tests/Manual/CPMenuCALayerTest/main.j
@@ -0,0 +1,18 @@
+/*
+ * AppController.j
+ * CPMenuCALayerTest
+ *
+ * Created by Mathieu Monney on December 19, 2014.
+ * Copyright 2014, Vidinoti SA, All rights reserved.
+ */
+
+@import <Foundation/Foundation.j>
+@import <AppKit/AppKit.j>
+
+@import "AppController.j"
+
+
+function main(args, namedArgs)
+{
+ CPApplicationMain(args, namedArgs);
+}
Something went wrong with that request. Please try again.