<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Cross-Platform &#8211; Xojo Programming Blog</title>
	<atom:link href="https://blog.xojo.com/category/cross-platform/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.xojo.com</link>
	<description>Blog about the Xojo programming language and IDE</description>
	<lastBuildDate>Wed, 08 Apr 2026 23:28:58 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<item>
		<title>Android Design Extensions 4.5</title>
		<link>https://blog.xojo.com/2026/04/09/android-design-extensions-4-5/</link>
		
		<dc:creator><![CDATA[Martin T.]]></dc:creator>
		<pubDate>Thu, 09 Apr 2026 15:00:00 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Community]]></category>
		<category><![CDATA[Guest Post]]></category>
		<category><![CDATA[Android Design Extensions]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=16166</guid>

					<description><![CDATA[Xojo 2026r1 has just been released, and it was time to revisit and update the Android Design Extensions. They are now available in version 4.5.&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Xojo 2026r1 has just been released, and it was time to revisit and update the Android Design Extensions. They are now available in version 4.5. This release focuses on the MobileSlider control, which in Xojo 2026r1 now uses the modern Material Slider under the hood (<a href="https://developer.android.com/reference/com/google/android/material/slider/Slider" target="_blank" rel="noreferrer noopener">https://developer.android.com/reference/com/google/android/material/slider/Slider</a>). This update provides a huge number of new possibilities for customizing the appearance of the MobileSlider, giving your Android apps much greater flexibility in designing their UI.</p>



<p>In total, more than 60 new declares have been added for MobileSlider, allowing you to control virtually every UI parameter of the control—whether it’s the shape of the thumb, its color, the track colors (both for the active/left and inactive/right portions), and much more. You can also set the step size, similar to what you’re used to on the desktop.</p>



<figure class="wp-block-image size-large is-resized"><img fetchpriority="high" decoding="async" width="461" height="1024" src="https://blog.xojo.com/wp-content/uploads/2026/04/android-image-1-461x1024.png" alt="" class="wp-image-16167" style="aspect-ratio:0.5625;object-fit:cover;width:337px;height:auto" srcset="https://blog.xojo.com/wp-content/uploads/2026/04/android-image-1-461x1024.png 461w, https://blog.xojo.com/wp-content/uploads/2026/04/android-image-1-135x300.png 135w, https://blog.xojo.com/wp-content/uploads/2026/04/android-image-1-768x1707.png 768w, https://blog.xojo.com/wp-content/uploads/2026/04/android-image-1-691x1536.png 691w, https://blog.xojo.com/wp-content/uploads/2026/04/android-image-1-922x2048.png 922w, https://blog.xojo.com/wp-content/uploads/2026/04/android-image-1.png 1080w" sizes="(max-width: 461px) 100vw, 461px" /></figure>



<p>Just take a look at the updated Android Design Extensions demo app and try it out.</p>



<p>Feel free to take a look at the developer repository, create feature requests, and provide feedback on extending this extension library. I’m happy to receive any voluntary financial support for the work I’ve done so far, which you are welcome to share <a href="https://www.paypal.com/paypalme/MTrippensee">here</a>. You can download the project with many examples at <a href="https://github.com/XojoGermany/AndroidDesignExtensions" target="_blank" rel="noreferrer noopener">https://github.com/XojoGermany/AndroidDesignExtensions</a>.</p>



<p>Happy coding!</p>



<p><em>Martin T. is a Xojo MVP and has been very involved in testing Android support.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Code Signing on macOS: What Developers Need to Know, Part 4</title>
		<link>https://blog.xojo.com/2026/04/07/code-signing-on-macos-what-developers-need-to-know-part-4/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Tue, 07 Apr 2026 19:00:00 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Tutorials]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=16119</guid>

					<description><![CDATA[In the previous article, we saw how signing a macOS app is more than just handling certificates. Other factors come into play based on the&#8230;]]></description>
										<content:encoded><![CDATA[
<p>In the <a href="https://blog.xojo.com/2026/03/24/code-signing-on-macos-what-developers-need-to-know-part-3/" target="_blank" rel="noreferrer noopener">previous article</a>, we saw how signing a macOS app is more than just handling certificates. Other factors come into play based on the distribution method you choose and the features it will offer.</p>



<span id="more-16119"></span>



<p>Now, that we already know all the pieces involved in this particular puzzle (certificates, <a href="https://blog.xojo.com/2024/12/10/sandboxing-hardened-runtime-and-notarization-arrives-to-the-xojo-ide/">sandboxing, notarization, hardened runtime</a>, etc.), the question to answer is…</p>



<h2 class="wp-block-heading">What kind of macOS code signing do you want to do today?</h2>



<p>Apple developer certificates installed on your Mac determine the kind of code signing and, thus, the distribution options available for your macOS app. They can also support certain macOS security requirements that distribution methods or features may impose, such as entitlements or provisioning profiles.</p>



<p>This diagram can help determine these based on the certificate used when signing the app, so you can get a better idea:</p>


<div class="wp-block-image">
<figure class="aligncenter"><a href="https://blog.xojo.com/wp-content/uploads/2026/04/macOS-Apps-SigningC-scaled.png"><img decoding="async" width="2560" height="678" src="https://blog.xojo.com/wp-content/uploads/2026/04/macOS-Apps-SigningC-scaled.png" alt="" class="wp-image-16122" srcset="https://blog.xojo.com/wp-content/uploads/2026/04/macOS-Apps-SigningC-scaled.png 2560w, https://blog.xojo.com/wp-content/uploads/2026/04/macOS-Apps-SigningC-300x79.png 300w, https://blog.xojo.com/wp-content/uploads/2026/04/macOS-Apps-SigningC-1024x271.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/04/macOS-Apps-SigningC-768x203.png 768w, https://blog.xojo.com/wp-content/uploads/2026/04/macOS-Apps-SigningC-1536x407.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/04/macOS-Apps-SigningC-2048x542.png 2048w" sizes="(max-width: 2560px) 100vw, 2560px" /></a></figure>
</div>


<p>As a practical summary:</p>



<ul class="wp-block-list">
<li><strong>Ad-Hoc signing / None</strong>: This option makes sense primarily when you&#8217;re developing and running or debugging the app on your Mac or on the same computer, since it typically doesn&#8217;t require special entitlements or provisioning profiles.</li>



<li><strong>Apple Developer / Development</strong>. Using this certificate enables sandboxing, hardened runtime, entitlements and provisioning profiles even when debugging from the IDE or testing the build on your own computer. It offers a better experience, but you won&#8217;t be able to notarize it or bypass the Gatekeeper barrier if distributed to other users.</li>



<li><strong>Developer ID Application / Direct Distribution</strong>. With this certificate, you can notarize your app so Gatekeeper won’t block distribution outside the Mac App Store. When debugging from the IDE, entitlements and provisioning profiles (if needed) are applied as well, along with optional sandboxing.</li>



<li><strong>Apple Distribution / App Store</strong>. Use this certificate when the app has been tested and it is ready to be sent to App Store Connect… or even when you&#8217;re planning to send it to the App Store Connect so a group of beta-testers can test it using Apple&#8217;s TestFlight.</li>
</ul>



<h2 class="wp-block-heading">How the Xojo IDE helps with all of this?</h2>



<p>We have been adding features to the Xojo IDE to make code signing and distributing your macOS apps an easier and leaner process; most of these are available under Build Settings > macOS > Sign:</p>



<h3 class="wp-block-heading">Developer ID &#8211; Build For</h3>



<p>This is the <a href="https://blog.xojo.com/2026/03/31/team-based-signing-arrives-to-macos/" target="_blank" rel="noreferrer noopener">most recent addition</a> to better deal with the first, and most important, piece of the puzzle: handling certificates! Instead of having to go back and forth between the Keychain Access and the Xojo IDE to copy/paste the expected data from the certificates for the kind of build or distribution you plan for the app, you can now find under the Developer ID field all the available Developer Teams (usually just yours) and, when a Developer Team is selected, the &#8220;Build For&#8221; popup menu will be populated with the available options for builds/distributions based on the installed developer certificates for that team.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img decoding="async" width="834" height="634" src="https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-11.50.45.png" alt="" class="wp-image-16137" srcset="https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-11.50.45.png 834w, https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-11.50.45-300x228.png 300w, https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-11.50.45-768x584.png 768w" sizes="(max-width: 834px) 100vw, 834px" /></figure>
</div>


<p>When all the Apple developer certificates are properly installed for a given Developer Team, the available options will be: Development, Direct Distribution and App Store (plus None, meaning Ad-Hoc signing).</p>



<p>If you find that some of these options are missing from the &#8220;Build For&#8221; popup menu, that means the corresponding certificate is not installed or there is some kind of issue with that certificate (maybe it has expired or has its private key missing). In those cases, we included the &#8220;Inspect…&#8221; option under the &#8220;Developer ID&#8221; popup menu. Selecting Inspect lets you gain a better picture about everything related to your Apple developer certificates and even get advice about how to fix the most common issues.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1914" height="1560" src="https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-11.53.39.png" alt="" class="wp-image-16138" srcset="https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-11.53.39.png 1914w, https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-11.53.39-300x245.png 300w, https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-11.53.39-1024x835.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-11.53.39-768x626.png 768w, https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-11.53.39-1536x1252.png 1536w" sizes="auto, (max-width: 1914px) 100vw, 1914px" /></figure>
</div>


<h3 class="wp-block-heading">Sandboxing</h3>



<p>Enable this feature if you plan to debug, build, or distribute your app as a sandboxed app. In that case, the associated editor will make it even easier to enable the sandboxing features that may apply to your particular app. The IDE will take care of all the rest. Note that, while sandboxing was previously only applied to built/distributed macOS apps in previous Xojo releases, starting with Xojo 2026r1 it is also applied when the app is being debugged from the IDE.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1012" height="1260" src="https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-11.55.02.png" alt="" class="wp-image-16139" srcset="https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-11.55.02.png 1012w, https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-11.55.02-241x300.png 241w, https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-11.55.02-822x1024.png 822w, https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-11.55.02-768x956.png 768w" sizes="auto, (max-width: 1012px) 100vw, 1012px" /></figure>
</div>


<h3 class="wp-block-heading">Hardened Runtime</h3>



<p>Enable this option mainly for apps meant to be built and/or distributed using Direct Distribution or the App Store options. While this is optional when distributing it via the Mac App Store, it is still highly recommended to enable it for that scenario.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1140" height="1408" src="https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-11.55.45.png" alt="" class="wp-image-16140" srcset="https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-11.55.45.png 1140w, https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-11.55.45-243x300.png 243w, https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-11.55.45-829x1024.png 829w, https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-11.55.45-768x949.png 768w" sizes="auto, (max-width: 1140px) 100vw, 1140px" /></figure>
</div>


<p>When the app is debugged from the IDE, the hardened runtime won&#8217;t be applied even if it is enabled… mainly so you can debug it!</p>



<p>As with sandboxing, the hardened runtime option also includes its own editor to make your app-specific selections easier. The IDE will take care of the under the hood processing when the app is built.</p>



<h3 class="wp-block-heading">Notarization</h3>



<p>If you haven&#8217;t started notarizing your macOS apps yet, now is the time! This will be possible only with the Direct Distribution option (equivalent to the Developer ID Application Certificate) and implies enabling hardened runtime. When you enable notarization, the associated hardened runtime will be enabled for you, even if you don&#8217;t select additional option from its editor.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1524" height="950" src="https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-12.13.18.png" alt="" class="wp-image-16147" srcset="https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-12.13.18.png 1524w, https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-12.13.18-300x187.png 300w, https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-12.13.18-1024x638.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-12.13.18-768x479.png 768w" sizes="auto, (max-width: 1524px) 100vw, 1524px" /></figure>
</div>


<p>Notarization requires the use of what Apple calls an <a href="https://support.apple.com/en-us/102654" target="_blank" rel="noreferrer noopener">App-Specific Password</a>, which you can set up by following the steps found in the window that appears when the associated Setup button is clicked.</p>



<p>Once everything has been setup, the notarization process will happen the next time the app is built. Note, the notarization process will not take place when the app is debugged from the IDE (as with hardened runtime); you don&#8217;t need to specifically disable that option.</p>



<h3 class="wp-block-heading">Entitlements</h3>



<p>The combination of certain certificates, build, and distribution options you choose for your app may require you to set a series of entitlements; for example, when enabling sandboxing and/or hardened runtime. Additionally, with Xojo 2026r1 it is possible to attach your built or debugged apps to Xcode Instruments for further inspections beyond the current capabilities of Xojo&#8217;s debugger.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="806" height="76" src="https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-11.56.55.png" alt="" class="wp-image-16142" srcset="https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-11.56.55.png 806w, https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-11.56.55-300x28.png 300w, https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-11.56.55-768x72.png 768w" sizes="auto, (max-width: 806px) 100vw, 806px" /></figure>
</div>


<p>In all of the above scenarios, Xojo will take care of the required entitlements without you needing to notice it; but if your app also makes use of some features that require adding extra entitlements (and probably a matching provisioning profile), as happens with most of the Apple specific services such as iCloud, Keychain, In-App Purchases, etc., you will need to craft the corresponding .plist file for them and add it using the User Entitlements option. These entitlements will be combined with the ones automatically generated by Xojo and included in the app during the code signing process.</p>



<h3 class="wp-block-heading">Provisioning Profiles</h3>



<p>On macOS, provisioning profiles are supported by a Copy Files build step, which requires selecting Contents as the destination folder. Not ideal, but that way you can select what kind of provisioning profile you want to apply to builds or when debugging your project (this is a new feature starting with Xojo 2026r1).</p>



<h3 class="wp-block-heading">Property List Editor</h3>



<p>The ability to add your own property list entries to the compiled/distributed macOS app is enhanced by a complete Property List Editor available under Build Settings &gt; macOS since Xojo 2025. It makes it easier to create these entries and even save them for reuse in other projects.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1424" height="1088" src="https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-11.58.09.png" alt="" class="wp-image-16143" srcset="https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-11.58.09.png 1424w, https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-11.58.09-300x229.png 300w, https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-11.58.09-1024x782.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-11.58.09-768x587.png 768w" sizes="auto, (max-width: 1424px) 100vw, 1424px" /></figure>
</div>


<p>The entries you add with the Property List Editor will be combined with those automatically generated by the IDE, or with entries that may have been added to the project using previous methods (such as adding an external .plist file to the Project Navigator sidebar).</p>



<h3 class="wp-block-heading">Publishing to the Mac App Store</h3>



<p>While there are some steps that need to be done both at <a href="https://developer.apple.com" target="_blank" rel="noreferrer noopener">Apple&#8217;s Developers Portal</a> and <a href="https://appstoreconnect.apple.com/login" target="_blank" rel="noreferrer noopener">App Store Connect Website</a>, you will be able to set your app category directly from the IDE under Build Settings &gt; macOS.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="816" height="184" src="https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-11.59.23.png" alt="" class="wp-image-16144" srcset="https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-11.59.23.png 816w, https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-11.59.23-300x68.png 300w, https://blog.xojo.com/wp-content/uploads/2026/04/Screenshot-2026-04-02-at-11.59.23-768x173.png 768w" sizes="auto, (max-width: 816px) 100vw, 816px" /></figure>
</div>


<p>In addition, the Publish feature (responsible for sending your app to App Store Connect) will be in charge of verifying that the project meets everything that Apple requires prior to send it for reviewing or making available through TestFlight.</p>



<p>In order for the Publish button to be enabled, you need to select the App Store option for the selected &#8220;Developer ID&#8221; Team from the &#8220;Build For&#8221; popup menu under Build Settings > macOS > Sign.</p>



<h2 class="wp-block-heading">Dealing with Certificates Issues</h2>



<p>It doesn&#8217;t matter if your app requires entitlements, provisioning profiles, or if you are going to notarize it or enable sandboxing plus hardened runtime. All of this is based on the signing of your developer certificates, so let&#8217;s go back and see how to deal with the most common issues related with these.</p>



<h3 class="wp-block-heading">Backup Your Certificates</h3>



<p>Once you have installed your certificates, the first thing you should do is export them from Keychain Access to a secure place (ideally, not in your computer but an external USB key or drive). Why? Here&#8217;s why:</p>



<ol class="wp-block-list">
<li>Apple only allows you to create certificates a maximum of five times per year (mostly because they expire after one year, <a href="https://blog.xojo.com/2026/03/04/code-signing-on-macos-what-developers-need-to-know-part-1/" target="_blank" rel="noreferrer noopener">as we did see in a previous entry</a>). Every time you install certificates, whether on the same computer or a different Mac you own, they count as new certificates, with different serial numbers and SHA1/SHA256 data. In practice, this reduces the number of installations available per year.</li>



<li>In addition, some features, like provisioning profiles, rely on the specific certificates selected during their creation. You will get a signing error if you build the app on a Mac with different certificates.</li>



<li>If you need to restore your Mac or migrate to a new Mac, your certificates won&#8217;t be restored using the usual tools from Apple. Having a backup of your developer certificates will make easier to restore them in Keychain Access after restoring your computer or when you change to a new Mac.</li>
</ol>



<p>Instead of using Xcode to install new certificates on every Mac you intend to use for code signing, install them on just one Mac, export them from that Mac, and import them into the Keychain Access app on your other Macs. This ensures all of your Macs will use the same certificates.</p>



<h3 class="wp-block-heading">Review Pending Apple Developer Agreements</h3>



<p>This is one of the most common issues related to code signing: it just stops working and you don&#8217;t know why and even the returned error messages doesn&#8217;t reveal why. If you&#8217;re sure you have the required developer certificates installed, they are valid (not expired), and don&#8217;t have any other issues then it is time to sign-in into the Apple Developer and App Store Connect portals to check if there are some pending agreements you need to accept.</p>



<h3 class="wp-block-heading">Missing and Expired Certificates</h3>



<p>This is another very common issue. Starting with Xojo 2026r1, we made easier to detect this situation. If a given certificate for your team is not installed, then you won&#8217;t be able to select the signing option from the &#8220;Build For&#8221; popup menu under Build Settings > macOS > Sign. You can further dig into it selecting the &#8220;Inspect…&#8221; option from the &#8220;Developer ID&#8221; popup menu, and even receive some advice on how to fix it!</p>



<h3 class="wp-block-heading">Certificates are all good…&nbsp;but the signing throws errors</h3>



<p>When using the Direct Distribution or App Store options, the code signing process uses Apple Time Servers to add the date and time as part of the signing. That means that the computer requires an active Internet connection, and that such time servers must be reachable from Apple’s side (it’s very rare for them to be down).</p>



<p>Other operations such as notarization and publish also require an active Internet connection, and the corresponding Apple services must be up and running. Some times these can be down.</p>



<p>When these issues occur, it is a good idea to check the <a href="https://developer.apple.com/system-status/" target="_blank" rel="noreferrer noopener">Apple Services status webpage</a>.</p>



<h2 class="wp-block-heading">In summary</h2>



<p>It&#8217;s been a long four-article ride with the aim of giving you a clearer understanding of what happens under the hood when you code sign your macOS apps, what kind of certificate you need for a given distribution, and which macOS security features are supported by Development, Developer ID Application or Apple Distribution certificates; and, most importantly, how Xojo helps you with all of it!</p>



<p>I&#8217;d love to hear about your experience with macOS code signing, the rough corners you still need to tackle, and other improvements you would welcome. The <a href="https://forum.xojo.com" target="_blank" rel="noreferrer noopener">Xojo forums</a> are a great place to keep the conversation going!</p>



<p>Happy macOS code signing with Xojo!</p>



<p><em>Javier Menendez is an engineer at Xojo and has been using Xojo since 1998. He lives in Castellón</em>, <em>Spain and hosts regular Xojo hangouts en español. Ask Javier questions on Twitter at <a href="https://twitter.com/xojoes" target="_blank" rel="noreferrer noopener">@XojoES</a> or on the <a href="https://forum.xojo.com/u/javier_menendez/summary" target="_blank" rel="noreferrer noopener">Xojo Forum</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p><strong>Code Signing on macOS: What Developers Need to Know</strong></p>



<ul class="wp-block-list">
<li><a href="https://blog.xojo.com/2026/03/04/code-signing-on-macos-what-developers-need-to-know-part-1/" target="_blank" rel="noreferrer noopener">Part 1, Get Started</a></li>



<li><a href="https://blog.xojo.com/2026/03/18/code-signing-on-macos-what-developers-need-to-know-part-2/" target="_blank" rel="noreferrer noopener">Part 2, Code Signing With Developer Certificates</a></li>



<li><a href="https://blog.xojo.com/2026/03/24/code-signing-on-macos-what-developers-need-to-know-part-3/">Part 3, Entitlements and Provisioning Profiles</a></li>



<li><a href="https://blog.xojo.com/2026/04/07/code-signing-on-macos-what-developers-need-to-know-part-4/" target="_blank" rel="noreferrer noopener">Part 4, How Xojo helps with Certificates, Signing and Distribution</a></li>
</ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Using Custom URI to Compliment your Web Application</title>
		<link>https://blog.xojo.com/2026/04/06/using-custom-uri-to-compliment-your-web-application/</link>
		
		<dc:creator><![CDATA[Wayne Golding]]></dc:creator>
		<pubDate>Mon, 06 Apr 2026 14:10:00 +0000</pubDate>
				<category><![CDATA[Community]]></category>
		<category><![CDATA[Guest Post]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[Custom URI URL Protocol]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=16094</guid>

					<description><![CDATA[There are times when you will want to use the resources of your web application’s user computer, for example, printing a sales docket for a&#8230;]]></description>
										<content:encoded><![CDATA[
<p>There are times when you will want to use the resources of your web application’s user computer, for example, printing a sales docket for a Point-Of-Sale site. In this article, I will expand on William Yu’s blog post <a href="https://blog.xojo.com/2016/08/16/custom-uri-schemes-on-windows/">Custom URI Schemes On Windows</a> from 2016. Again, I’m going to use a simple alert-type application, add an Inno Setup script to install the client app, and show how to invoke that app from your web application.</p>



<p>First, I’m going to create a headless desktop application. A console application would work, but shows a command box.</p>



<p>In the Xojo IDE, create a new desktop project and delete Window1 and MainMenuBar. Then add the Opening Event Handler to App and add this code:</p>



<pre class="wp-block-code"><code>Self.AllowAutoQuit = True</code></pre>



<p>This will allow the application to quit when done.</p>



<p>Add the DocumentOpened Event Handler to App and add this code:</p>



<pre class="wp-block-code"><code>If item _ ' Using item
 .NativePath _ ' property NativePath
 .NthField(":", 1) &lt;> "AlertDemo" Then ' Compare the value left of the ":"
 Return ' If invalid return (quit)
End If
Var alert As String ' Define the variable
alert = item _ ' Using Item
 .NativePath _ ' property NativePath
 .NthField(":", 2) ' Extract the contents to the right of the ":"

alert = DecodeURLComponent(alert) ' Convert the content to plain text
MessageBox(alert) ' Show the alert
' The app will now quit</code></pre>



<p>To test you can select Shared in Build Settings.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="366" height="183" src="https://blog.xojo.com/wp-content/uploads/2026/03/image.png" alt="" class="wp-image-16095" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/image.png 366w, https://blog.xojo.com/wp-content/uploads/2026/03/image-300x150.png 300w" sizes="auto, (max-width: 366px) 100vw, 366px" /></figure>



<p><br>And enter a value into Command Line Arguments:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="595" height="126" src="https://blog.xojo.com/wp-content/uploads/2026/03/image-1.png" alt="" class="wp-image-16096" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/image-1.png 595w, https://blog.xojo.com/wp-content/uploads/2026/03/image-1-300x64.png 300w" sizes="auto, (max-width: 595px) 100vw, 595px" /></figure>



<p><br>Running the app in debug mode will show:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="231" height="237" src="https://blog.xojo.com/wp-content/uploads/2026/03/image-2.png" alt="" class="wp-image-16097"/></figure>



<p><br>Now build the project and create an installer using <a href="https://jrsoftware.org/isinfo.php">Inno Setup</a>.</p>



<pre class="wp-block-preformatted">[Setup]<br>AppId={{B4D9ABDA-9F58-4FE0-A5F3-3E39C28EAB59}<br>AppName=Alert Demo<br>AppVersion=1.0<br>DefaultDirName={commonpf64}\Axis Direct Ltd\Alert Demo<br>DefaultGroupName=Axis Direct<br>OutputDir=C:\Xojo Projects\Alert Demo\Installer<br>OutputBaseFilename=AlertDemoInstaller<br>Compression=lzma<br>SolidCompression=yes<br>ChangesEnvironment=yes<br>[Languages]<br>Name: "english"; MessagesFile: "compiler:Default.isl"<br>[Tasks]<br>[Dirs]<br>Name: "{app}\Alert Demo Libs"<br>[Files]<br>Source: "C:\Xojo Projects\Alert Demo\Project\Builds - Alert<br>Demo\Windows 64 bit\Alert Demo*"; DestDir: "{app}"; Flags:<br>ignoreversion<br>Source: "C:\Xojo Projects\Alert Demo\Project\Builds - Alert<br>Demo\Windows 64 bit\Alert Demo\Alert Demo Libs*"; DestDir:<br>"{app}\Alert Demo Libs"; Flags: ignoreversion<br>[Icons]<br>[Run]<br>[Registry]<br>Root: HKCR; Subkey: "AlertDemo"; Flags: uninsdeletekey<br>Root: HKCR; Subkey: "AlertDemo"; ValueType: "String";<br>ValueData: "URL:AlertDemo Protocol"; Flags: uninsdeletekey<br>Root: HKCR; Subkey: "AlertDemo"; ValueName: "URL Protocol";<br>ValueType: "String"; ValueData: ""; Flags: uninsdeletekey<br>Root: HKCR; Subkey: "AlertDemo\shell"; Flags: uninsdeletekey<br>Root: HKCR; Subkey: "AlertDemo\shell\open"; Flags:<br>uninsdeletekey<br>Root: HKCR; Subkey: "AlertDemo\shell\open\command"; Flags:<br>uninsdeletekey<br>Root: HKCR; Subkey: "AlertDemo\shell\open\command";<br>ValueType: String; ValueData: "{app}\Alert Demo.exe %1";<br>Flags: uninsdeletekey</pre>



<p>The registry section creates the registry entries per <a href="https://blog.xojo.com/2016/08/16/custom-uri-schemes-on-windows/">William’s blog post</a>.</p>



<p>Now that the application Is installed, we’ll look at the Web Application. For the sake of testing, I’m just adding a Button to a WebPage and adding the following code into the pressed event.</p>



<pre class="wp-block-code"><code>Var s As String = "Hello World"
Var Alert As String
Alert = EncodeURLComponent(s) ' Make the string URL safe
GoToURL("AlertDemo:" + Alert, True) ' Launch the app in a new tab</code></pre>



<p>And that is it!</p>



<p>For printing a docket, I would pass a unique identifier for the transaction using this method then access the data using URLConnection &amp; HandleURL.</p>



<p><em>Wayne Golding has been a Xojo developer since 2005 and is a Xojo MVP. He operates the IT Company <a href="http://www.axisdirect.nz">Axis Direct Ltd </a>which primarily develops applications using Xojo that integrate with Xero www.xero.com. Wayne’s hobby is robotics where he uses Xojo to build applications for his Raspberry Pi, often implementing IoT for remote control.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Build a Simple Find in Files Function</title>
		<link>https://blog.xojo.com/2026/04/02/build-a-simple-find-in-files-function/</link>
		
		<dc:creator><![CDATA[Gabriel Ludosanu]]></dc:creator>
		<pubDate>Thu, 02 Apr 2026 16:15:00 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Files]]></category>
		<category><![CDATA[Search]]></category>
		<category><![CDATA[Text Files]]></category>
		<category><![CDATA[Text Processing]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15972</guid>

					<description><![CDATA[Sooner or later most apps need some version of the ability to find text in those files, whether you&#8217;re scanning log files, config files, exported&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Sooner or later most apps need some version of the ability to find text in those files, whether you&#8217;re scanning log files, config files, exported data, or source code.</p>



<p>In this post, we&#8217;ll build a simple Find in Files utility in Xojo that:</p>



<ul class="wp-block-list">
<li>searches the files in a folder</li>



<li>reads each file line by line</li>



<li>performs a plain-text, case-insensitive match</li>



<li>returns the file path, line number, and matching line</li>
</ul>



<p>The goal is simple: build something useful while leaving the door open for the fancier stuff.</p>



<h2 class="wp-block-heading" id="what-this-find-in-files-function-will-do">What this Find in Files function will do</h2>



<p>Let&#8217;s keep the scope clear:</p>



<ul class="wp-block-list">
<li>search one folder</li>



<li>search plain text only</li>



<li>skip subfolders for now</li>



<li>return the matching file path, line number, and line contents</li>
</ul>



<h2 class="wp-block-heading" id="step-1-put-the-result-class-in-the-module">Step 1: A class in a module and some properties</h2>



<p>Before touching the file system, let&#8217;s define what a match looks like.</p>



<p>You could return raw strings, but that gets messy fast. A small class keeps the code readable and gives us an obvious place to extend later. In this version, I like keeping that class inside the same module as the search function. It keeps the entire utility self-contained instead of spraying helper types all over the project.</p>



<p>So, we start by adding a module&nbsp;<code>SearchUtils</code>&nbsp;and inside the module we will add a class&nbsp;<code>SearchHit</code>.</p>



<pre class="wp-block-code"><code>Module SearchUtils

  Class SearchHit

    Public Property FilePath As String
    Public Property LineNumber As Integer
    Public Property LineText As String

    Public Sub Constructor(filePath As String, lineNumber As Integer, lineText As String)
      Self.FilePath = filePath
      Self.LineNumber = lineNumber
      Self.LineText = lineText
    End Sub

  End Class

End Module</code></pre>



<p>Each result stores three things:</p>



<ol class="wp-block-list">
<li>the file path</li>



<li>the line number</li>



<li>the matching line</li>
</ol>



<h2 class="wp-block-heading" id="step-2-walk-through-the-folder">Step 2: Walk through the folder</h2>



<p><code>FolderItem.Children</code> lets us loop through a folder with a <code>For Each</code> loop, which keeps the code clear.</p>



<p>We&#8217;ll also reject bad input early:</p>



<ul class="wp-block-list">
<li>the folder is&nbsp;<code>Nil</code></li>



<li>the folder does not exist</li>



<li>the item passed is not actually a folder</li>



<li>the search term is empty</li>
</ul>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="409" src="https://blog.xojo.com/wp-content/uploads/2026/03/find_in_files_xojo_function_diagram2-1024x409.png" alt="" class="wp-image-16027" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/find_in_files_xojo_function_diagram2-1024x409.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/03/find_in_files_xojo_function_diagram2-300x120.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/find_in_files_xojo_function_diagram2-768x307.png 768w, https://blog.xojo.com/wp-content/uploads/2026/03/find_in_files_xojo_function_diagram2.png 1536w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>This process is simple, fast and effective.</p>



<h2 class="wp-block-heading" id="step-3-read-files-line-by-line">Step 3: Read files line by line</h2>



<p>For text files,&nbsp;<code>TextInputStream.Open</code>&nbsp;is the right tool. From there, we can call&nbsp;<code>ReadLine</code>&nbsp;until&nbsp;<code>EndOfFile</code>&nbsp;becomes&nbsp;<code>True</code>.</p>



<p>I prefer this over&nbsp;<code>ReadAll</code>&nbsp;for a utility like this.&nbsp;<code>ReadAll</code>&nbsp;is fine when the file is small and you know what you&#8217;re doing, but line-by-line reading is a better default here. It keeps memory use in check and gives us line numbers for free.</p>



<p>For the sample code, I&#8217;m explicitly using UTF-8:</p>



<pre class="wp-block-code"><code>input.Encoding = Encodings.UTF8</code></pre>



<p>That keeps the sample predictable. It does&nbsp;<strong>not</strong>&nbsp;mean this code can gracefully decode every text file you throw at it. Files with unknown encodings or binary-ish content are a separate problem, and they deserve their own solution.</p>



<h2 class="wp-block-heading" id="step-4-match-the-text">Step 4: Match the text</h2>



<p>For a plain-text search,&nbsp;<code>String.Contains</code>&nbsp;does exactly what we need:</p>



<pre class="wp-block-code"><code>line.Contains(searchTerm, ComparisonOptions.CaseInsensitive)</code></pre>



<p>It handles the case-insensitivity without the overhead, or the headache, of regex.</p>



<h2 class="wp-block-heading" id="step-5-the-full-module">Step 5: The full module and class and function</h2>



<pre class="wp-block-code"><code>Module SearchUtils

  Public Class SearchHit
    Public Property FilePath As String
    Public Property LineNumber As Integer
    Public Property LineText As String

    Public Sub Constructor(filePath As String, lineNumber As Integer, lineText As String)
      Self.FilePath = filePath
      Self.LineNumber = lineNumber
      Self.LineText = lineText
    End Sub
  End Class

  Public Function FindInFiles(targetFolder As FolderItem, searchTerm As String) As SearchHit()
    Var hits() As SearchHit

    If targetFolder Is Nil Then
      Return hits
    End If

    If Not targetFolder.Exists Or Not targetFolder.IsFolder Then
      Return hits
    End If

    If searchTerm.IsEmpty Then
      Return hits
    End If

    For Each item As FolderItem In targetFolder.Children
      If item Is Nil Then Continue
      If item.IsFolder Then Continue
      If Not item.Exists Then Continue
      If Not item.IsReadable Then Continue

      Try
        Var input As TextInputStream = TextInputStream.Open(item)
        input.Encoding = Encodings.UTF8

        Var lineNumber As Integer = 0

        While Not input.EndOfFile
          Var line As String = input.ReadLine
          lineNumber = lineNumber + 1

          If line.Contains(searchTerm, ComparisonOptions.CaseInsensitive) Then
            hits.Add(New SearchHit(item.NativePath, lineNumber, line))
          End If
        Wend

        input.Close

      Catch error As IOException
        ' Skip files that cannot be read as text.
        Continue
      End Try
    Next

    Return hits
  End Function

End Module</code></pre>



<h2 class="wp-block-heading" id="how-it-works">How it works</h2>



<p>Let&#8217;s break down the important parts.</p>



<h3 class="wp-block-heading" id="input-validation">Input validation</h3>



<p>This block prevents pointless work and avoids avoidable runtime problems:</p>



<pre class="wp-block-code"><code>If targetFolder Is Nil Then
  Return hits
End If

If Not targetFolder.Exists Or Not targetFolder.IsFolder Then
  Return hits
End If

If searchTerm.IsEmpty Then
  Return hits
End If</code></pre>



<p>Rule of thumb: reject bad input early.</p>



<h3 class="wp-block-heading" id="folder-iteration">Folder iteration</h3>



<p>This is the core loop:</p>



<pre class="wp-block-code"><code>For Each item As FolderItem In targetFolder.Children</code></pre>



<p>We&#8217;re only scanning the folder&#8217;s immediate contents. If an item is another folder, we skip it.</p>



<pre class="wp-block-code"><code>If item.IsFolder Then Continue</code></pre>



<h3 class="wp-block-heading" id="safe-text-reading">Safe text reading</h3>



<p>Each file is opened with&nbsp;<code>TextInputStream.Open</code>&nbsp;inside a&nbsp;<code>Try...Catch</code>&nbsp;block:</p>



<pre class="wp-block-code"><code>Try
  Var input As TextInputStream = TextInputStream.Open(item)
  input.Encoding = Encodings.UTF8
  ...
Catch error As IOException
  Continue
End Try</code></pre>



<p>That way, one unreadable file does not take down the whole search. It gets skipped and the rest of the folder still gets processed.</p>



<h3 class="wp-block-heading" id="line-by-line-matching">Line-by-line matching</h3>



<p>This is where the actual work happens:</p>



<pre class="wp-block-code"><code>While Not input.EndOfFile
  Var line As String = input.ReadLine
  lineNumber = lineNumber + 1

  If line.Contains(searchTerm, ComparisonOptions.CaseInsensitive) Then
    hits.Add(New SearchHit(item.NativePath, lineNumber, line))
  End If
Wend</code></pre>



<p>Because we&#8217;re reading one line at a time, attaching the correct line number is trivial.</p>



<h3 class="wp-block-heading" id="why-keep-searchhit-inside-the-module">Why keep&nbsp;<code>SearchHit</code>&nbsp;inside the module?</h3>



<p>Because it belongs to this utility. The search function and its result type are part of the same little unit of behavior, so keeping them together makes the project easier to scan and easier to transform it to a&nbsp;<a href="https://documentation.xojo.com/topics/code_management/sharing_code_among_multiple_projects.html" target="_blank" rel="noreferrer noopener">Library</a>.</p>



<p>It also means code outside the module uses the namespaced type:</p>



<pre class="wp-block-code"><code>Var results() As SearchUtils.SearchHit = SearchUtils.FindInFiles(folder, "xojo")</code></pre>



<h2 class="wp-block-heading" id="using-the-function">Using the function</h2>



<p>Here&#8217;s a simple example that lets the user choose a folder and then writes the results to the debug log:</p>



<pre class="wp-block-code"><code>Var folder As FolderItem = FolderItem.ShowSelectFolderDialog
If folder Is Nil Then Return

Var results() As SearchUtils.SearchHit = SearchUtils.FindInFiles(folder, "error")

For Each hit As SearchUtils.SearchHit In results
  System.DebugLog(hit.FilePath + " | line " + hit.LineNumber.ToString + " | " + hit.LineText)
Next</code></pre>



<p>If you want to display the results in a&nbsp;<code>DesktopListBox</code>, that works nicely too:</p>



<pre class="wp-block-code"><code>Var folder As FolderItem = FolderItem.ShowSelectFolderDialog
If folder Is Nil Then Return

Var results() As SearchUtils.SearchHit = FindInFiles(folder, "error")

ListBox1.RemoveAllRows
ListBox1.ColumnCount = 3

For Each hit As SearchUtils.SearchHit In results
  ListBox1.AddRow(hit.FilePath)
  ListBox1.CellTextAt(ListBox1.LastAddedRowIndex, 1) = hit.LineNumber.ToString
  ListBox1.CellTextAt(ListBox1.LastAddedRowIndex, 2) = hit.LineText
Next</code></pre>



<p>A few sample results might look like this:</p>



<pre class="wp-block-code"><code>C:\Logs\app.log | line 18 | Error connecting to database
C:\Logs\app.log | line 42 | Error writing audit record
C:\Configs\service.txt | line 7 | Last error message: timeout</code></pre>



<h2 class="wp-block-heading" id="practical-limitations-of-this-version">Practical limitations of this version</h2>



<p>This utility is useful, but limited.</p>



<h3 class="wp-block-heading" id="it-assumes-utf-8">It assumes UTF-8</h3>



<p>That is fine for plenty of modern text files, but not all of them. If you&#8217;re dealing with mixed encodings, you&#8217;ll need a smarter approach that detects the file encoding.</p>



<h3 class="wp-block-heading" id="it-doesnt-recurse-into-subfolders">It doesn&#8217;t recurse into subfolders</h3>



<p>That is deliberate. Recursive search is useful, but it adds another layer of behavior and another place to make the code harder to read.</p>



<h2 class="wp-block-heading" id="final-thoughts">Final thoughts</h2>



<p>A basic Find in Files function is one of those utilities that looks small but pays off quickly. This is a base-layer utility. Once you have this working, adding recursion or regex is a much smaller lift.</p>



<p>Let&#8217;s discuss in the&nbsp;<a href="https://forum.xojo.com/">forums</a>.</p>



<p><em>Gabriel is a digital marketing enthusiast who loves coding with Xojo to create cool software tools for any platform. He is always eager to learn and share new ideas!</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>More New Features for Android: MobileChart, MobileColorPicker, MobilePDFViewer &#038; Zip/Unzip</title>
		<link>https://blog.xojo.com/2026/03/31/more-new-features-for-android/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Tue, 31 Mar 2026 15:22:00 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[2026r1]]></category>
		<category><![CDATA[Charts]]></category>
		<category><![CDATA[PDF]]></category>
		<category><![CDATA[Unzip]]></category>
		<category><![CDATA[Zip]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=16035</guid>

					<description><![CDATA[The first release of 2026 brings some notable new features to Xojo’s Android support. You’ll find new charting, color-picking, PDF viewing, and file-zip utilities, plus&#8230;]]></description>
										<content:encoded><![CDATA[
<p>The first release of 2026 brings some notable new features to Xojo’s Android support. You’ll find new charting, color-picking, PDF viewing, and file-zip utilities, plus ongoing improvements to several controls. Here’s a quick tour of what’s new.</p>



<h2 class="wp-block-heading"><strong>MobileChart</strong></h2>



<p>Matching the features available for iOS, <a href="https://documentation.xojo.com/api/user_interface/mobile/mobilechart.html#mobilechart" target="_blank" rel="noreferrer noopener">MobileChart</a> lets you create a wide variety of charts to show in your Android app.</p>



<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" width="483" height="1024" src="https://blog.xojo.com/wp-content/uploads/2026/03/CleanShot-2026-03-24-at-13.19.47@2x-483x1024.png" alt="" class="wp-image-16036" style="width:198px;height:auto" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/CleanShot-2026-03-24-at-13.19.47@2x-483x1024.png 483w, https://blog.xojo.com/wp-content/uploads/2026/03/CleanShot-2026-03-24-at-13.19.47@2x-142x300.png 142w, https://blog.xojo.com/wp-content/uploads/2026/03/CleanShot-2026-03-24-at-13.19.47@2x-768x1628.png 768w, https://blog.xojo.com/wp-content/uploads/2026/03/CleanShot-2026-03-24-at-13.19.47@2x-725x1536.png 725w, https://blog.xojo.com/wp-content/uploads/2026/03/CleanShot-2026-03-24-at-13.19.47@2x.png 918w" sizes="auto, (max-width: 483px) 100vw, 483px" /></figure>



<h2 class="wp-block-heading"><strong>MobileColorPicker</strong></h2>



<p>This new control, <a href="https://documentation.xojo.com/api/user_interface/mobile/mobilecolorpicker.html#mobilecolorpicker" target="_blank" rel="noreferrer noopener">as its name suggests</a>, lets you use the system color picker to select a color.</p>



<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" width="481" height="1024" src="https://blog.xojo.com/wp-content/uploads/2026/03/CleanShot-2026-03-24-at-13.21.46@2x-481x1024.png" alt="" class="wp-image-16038" style="width:202px;height:auto" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/CleanShot-2026-03-24-at-13.21.46@2x-481x1024.png 481w, https://blog.xojo.com/wp-content/uploads/2026/03/CleanShot-2026-03-24-at-13.21.46@2x-141x300.png 141w, https://blog.xojo.com/wp-content/uploads/2026/03/CleanShot-2026-03-24-at-13.21.46@2x-768x1634.png 768w, https://blog.xojo.com/wp-content/uploads/2026/03/CleanShot-2026-03-24-at-13.21.46@2x-722x1536.png 722w, https://blog.xojo.com/wp-content/uploads/2026/03/CleanShot-2026-03-24-at-13.21.46@2x.png 912w" sizes="auto, (max-width: 481px) 100vw, 481px" /></figure>



<h2 class="wp-block-heading"><strong>MobilePDFViewer</strong></h2>



<p>Last year Android added <a href="https://documentation.xojo.com/api/pdf/pdfdocument.html#pdfdocument" target="_blank" rel="noreferrer noopener">PDFDocument</a> support for creating your own PDFs, and now we’ve added <a href="https://documentation.xojo.com/api/user_interface/mobile/mobilepdfviewer.html#methods" target="_blank" rel="noreferrer noopener">MobilePDFViewer</a> to give you an easy way to show PDF document files from your Android apps.</p>



<h2 class="wp-block-heading"><strong>Zip/Unzip</strong></h2>



<p>The FolderItem class now supports the <a href="https://documentation.xojo.com/api/files/folderitem.html#folderitem-zip" target="_blank" rel="noreferrer noopener">Zip</a> and <a href="https://documentation.xojo.com/api/files/folderitem.html#folderitem-unzip" target="_blank" rel="noreferrer noopener">Unzip</a> methods to make it simple to compress and uncompressed Zip files.</p>



<h2 class="wp-block-heading"><strong>Android Keeps Getting Better</strong></h2>



<p>There are also improvements to <a href="https://documentation.xojo.com/api/user_interface/mobile/mobiletabpanel.html#mobiletabpanel" target="_blank" rel="noreferrer noopener">MobileTabPanel</a>, <a href="https://documentation.xojo.com/api/user_interface/mobile/mobiletextarea.html#mobiletextarea" target="_blank" rel="noreferrer noopener">MobileTextArea</a>, <a href="https://documentation.xojo.com/api/user_interface/mobile/mobileslider.html#mobileslider" target="_blank" rel="noreferrer noopener">MobileSlider</a>, <a href="https://documentation.xojo.com/api/user_interface/mobile/mobilescrollablearea.html#mobilescrollablearea" target="_blank" rel="noreferrer noopener">MobileScrollableArea</a>, <a href="https://documentation.xojo.com/api/hardware/barcode.html#barcode" target="_blank" rel="noreferrer noopener">Barcode</a> and more. With each release, Android gets closer to feature parity with iOS!</p>



<p>And of course, we continue to squash framework and compiler bugs.</p>



<p>Be sure to check out the full <a href="https://documentation.xojo.com/resources/release_notes/2026r1.html" target="_blank" rel="noreferrer noopener">release notes</a> for all the details!</p>



<p><em>Paul learned to program in BASIC at age 13 and has programmed in more languages than he remembers, with Xojo being an obvious favorite. When not working on Xojo, you can find him talking about retrocomputing at <a href="https://goto10.substack.com" target="_blank" rel="noreferrer noopener">Goto 10</a> and </em>on Mastodon @lefebvre@hachyderm.io.</p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Custom Control Rendering with DrawControlInLayoutEditor</title>
		<link>https://blog.xojo.com/2026/03/31/custom-control-rendering-with-drawcontrolinlayouteditor/</link>
		
		<dc:creator><![CDATA[William Yu]]></dc:creator>
		<pubDate>Tue, 31 Mar 2026 15:22:00 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[2026r1]]></category>
		<category><![CDATA[DrawControlInLayoutEditor]]></category>
		<category><![CDATA[IDE]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=16045</guid>

					<description><![CDATA[One of the notable additions in Xojo 2026 Release 1 is that the&#160;DrawControlInLayoutEditor&#160;event is now available for Desktop and iOS/Android projects, giving you more possibilities&#8230;]]></description>
										<content:encoded><![CDATA[
<p>One of the notable additions in Xojo 2026 Release 1 is that the&nbsp;<code>DrawControlInLayoutEditor</code>&nbsp;event is now available for Desktop and iOS/Android projects, giving you more possibilities over how your controls appear in the layout editor.</p>



<p>With this feature you can provide custom drawing for a control at design time, making it easier to visualize your UI without running the project.</p>



<p>If this sounds familiar, it&#8217;s because it brings Desktop and iOS/Android projects closer to what&#8217;s already possible in Web projects with&nbsp;<code>WebSDKUIControl</code>, where custom layout rendering has been available for some time.</p>



<h4 class="wp-block-heading">Why this matters</h4>



<p>Previously your custom Canvas controls would appear as generic placeholders, making it difficult to understand how they would look at runtime. Now you can:</p>



<ul class="wp-block-list">
<li>Render a preview of your control directly in the layout editor</li>



<li>Display dynamic or state-based visuals</li>



<li>Make custom controls much easier to work with at design time</li>
</ul>



<h4 class="wp-block-heading">How it works</h4>



<p>For Desktop projects, you can subclass&nbsp;<code>DesktopUIControl</code>&nbsp;and implement the&nbsp;<code>DrawControlInLayoutEditor</code>&nbsp;event. Your drawing code is executed by the IDE as it renders the control in the layout. For iOS and Android projects, this event is available on&nbsp;<code>MobileUIControl</code>.</p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f449.png" alt="👉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> You can also use this event directly with&nbsp;<code>DesktopCanvas</code>&nbsp;and&nbsp;<code>MobileCanvas</code>&nbsp;controls, so you can start drawing in&nbsp;<code>DrawControlInLayoutEditor</code>&nbsp;without needing to subclass anything.</p>



<p>This event gives you the flexibility to draw whatever you need—shapes, text, or even simplified representations of runtime content. For example, a custom media player control could display a play button and timeline, or a chart control could render a sample graph.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="661" src="https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-24-at-3.03.15-PM-1024x661.png" alt="" class="wp-image-16049" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-24-at-3.03.15-PM-1024x661.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-24-at-3.03.15-PM-300x194.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-24-at-3.03.15-PM-768x496.png 768w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-24-at-3.03.15-PM-1536x991.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-24-at-3.03.15-PM-2048x1322.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h4 class="wp-block-heading">A note about XojoScript limitations</h4>



<p>One important detail to keep in mind is that&nbsp;<code>DrawControlInLayoutEditor</code>&nbsp;runs using XojoScript. This allows the IDE to safely execute your drawing code at design time, but it also means not everything you&#8217;d typically expect to use in Xojo is available, especially when it comes to the graphics APIs.</p>



<p>In practice, most common drawing operations—such as shapes, lines, and text—work as expected. However, in some cases these graphics calls use a slightly different API, as is the case with <code>LinearGradientBrush</code>.</p>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f449.png" alt="👉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Also, because this runs as XojoScript, you cannot call other methods from within your <code>DrawControlInLayoutEditor</code>code. To access your control&#8217;s properties, you&#8217;ll need to use the built-in  <code>ColorProperty</code>, <code>BooleanProperty</code>, <code>IntegerProperty</code>, <code>DoubleProperty</code>, and <code>StringProperty</code> methods.</p>



<h4 class="wp-block-heading">Support for more Graphics</h4>



<p>In 2026r1, we&#8217;ve expanded the graphics capabilities available to&nbsp;<code>DrawControlInLayoutEditor</code>, building on what was previously supported for&nbsp;<code>WebSDKUIControl</code>. New additions include support for:</p>



<ul class="wp-block-list">
<li>LinearGradientBrush, PictureBrush, and ShadowBrush</li>



<li>LineDash, LineDashOffset, LineCap, LineJoin, and MiterLimit</li>



<li>Outline</li>



<li>Scale, Rotate, and Translate</li>



<li>SaveState, RestoreState</li>



<li>Color constants (Red, Green, Blue, Yellow etc.)</li>
</ul>



<p>Since XojoScript does not support the&nbsp;<code>Pair</code>&nbsp;type, the&nbsp;<code>LinearGradientBrush</code>&nbsp;API was adapted slightly:</p>



<pre class="wp-block-code"><code>Class LinearGradientBrush

  Sub Constructor()

  Sub AddStop(stop As Double, c As Color)

  Property StartPoint As Point
  Property EndPoint As Point

End Class</code></pre>



<p>The main difference is how the brush is constructed and how stops are added, without needing&nbsp;<code>Pair</code>. With this new API, you can turn a basic graph into something much more visually appealing.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="661" src="https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-25-at-3.00.07-PM-1024x661.png" alt="" class="wp-image-16075" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-25-at-3.00.07-PM-1024x661.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-25-at-3.00.07-PM-300x194.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-25-at-3.00.07-PM-768x496.png 768w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-25-at-3.00.07-PM-1536x991.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-25-at-3.00.07-PM-2048x1322.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h4 class="wp-block-heading">Turning off this feature</h4>



<p>While many may prefer custom rendering for custom controls, it can become a bottleneck when a large number of controls are rendering content. If you prefer a less resource-intensive experience, you can disable this behavior in Settings → Layout by enabling the Static Rendering option.</p>



<h4 class="wp-block-heading">Finally</h4>



<p>With&nbsp;<code>DrawControlInLayoutEditor</code>&nbsp;now available for Desktop and Mobile projects, you can take advantage of the same benefits Web projects have enjoyed for years. Be sure to check out the new DrawControlInLayoutEditor example project, adapted from the WebSDK → CustomButton example. We hope you enjoy designing and previewing your custom controls with this new event—and yes, it also works in Libraries!</p>



<p><em><em><em>William Yu grew up in Canada learning to program BASIC on a Vic-20. He is Xojo’s resident Windows and Linux engineer, among his many other skills. Some may say he has joined the dark side here in the USA, but he will always be a Canadian at heart.</em></em></em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Scan Barcodes, Pick Colors, Toggle: Xojo Web in 2026r1</title>
		<link>https://blog.xojo.com/2026/03/31/scan-barcodes-pick-colors-toggle-xojo-web-in-2026r1/</link>
		
		<dc:creator><![CDATA[Ricardo Cruz]]></dc:creator>
		<pubDate>Tue, 31 Mar 2026 13:22:00 +0000</pubDate>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[2026r1]]></category>
		<category><![CDATA[Web 2.0]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[webdev]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<category><![CDATA[Xojo Web]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15969</guid>

					<description><![CDATA[If you build web apps with Xojo, 2026r1 is worth a close look. There&#8217;s a good mix of new controls and under-the-hood improvements to explore.&#8230;]]></description>
										<content:encoded><![CDATA[
<p>If you build web apps with Xojo, 2026r1 is worth a close look. There&#8217;s a good mix of new controls and under-the-hood improvements to explore. Exciting times!</p>



<h2 class="wp-block-heading">New Controls</h2>



<p>Three new controls have been added to the Web framework in this release, aiming to close the difference gap between Web and the other project types.</p>



<p><code>WebSwitch</code>&nbsp;is a toggle control that mobile developers will already be familiar with. It&#8217;s been available on iOS and Android for a while. It&#8217;s now available for web projects too, so if you&#8217;ve been approximating a toggle switch using a styled checkbox, you can finally retire that workaround.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="690" src="https://blog.xojo.com/wp-content/uploads/2026/03/switch-vs-checkbox-1024x690.png" alt="" class="wp-image-15992" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/switch-vs-checkbox-1024x690.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/03/switch-vs-checkbox-300x202.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/switch-vs-checkbox-768x517.png 768w, https://blog.xojo.com/wp-content/uploads/2026/03/switch-vs-checkbox-1536x1035.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/03/switch-vs-checkbox-2048x1380.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p><code>WebColorPicker</code> brings color selection to web apps in the same way <code>DesktopColorPicker</code> does for desktop. Drop it in from the Library, wire up the event and you have a color picker the Xojo way.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="731" src="https://blog.xojo.com/wp-content/uploads/2026/03/colorpicker-ide-1024x731.png" alt="" class="wp-image-15994" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/colorpicker-ide-1024x731.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/03/colorpicker-ide-300x214.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/colorpicker-ide-768x548.png 768w, https://blog.xojo.com/wp-content/uploads/2026/03/colorpicker-ide-1536x1096.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/03/colorpicker-ide-2048x1461.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>This is how <code>WebColorPicker</code> looks like in your browser:</p>



<figure class="wp-block-video"><video height="1274" style="aspect-ratio: 1488 / 1274;" width="1488" controls src="https://blog.xojo.com/wp-content/uploads/2026/03/colorpicker-browser.mp4"></video></figure>



<p>The third new control adds barcode reading support. Your web app can now read barcodes directly from the user&#8217;s camera, from desktop or mobile browsers. This opens up a lot of practical use cases: Inventory systems, ticketing, product lookups, that previously would have pushed you toward a native mobile app.</p>



<p>Again, drop the Barcode control into your project and implement the events:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="747" src="https://blog.xojo.com/wp-content/uploads/2026/03/barcode-reader-ide-1024x747.png" alt="" class="wp-image-15995" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/barcode-reader-ide-1024x747.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/03/barcode-reader-ide-300x219.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/barcode-reader-ide-768x560.png 768w, https://blog.xojo.com/wp-content/uploads/2026/03/barcode-reader-ide-1536x1120.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/03/barcode-reader-ide-2048x1494.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>That&#8217;s it! Your web apps can scan a great variety of barcodes now. Including QR, Data Matrix, Aztec, PDF 417 and much more!</p>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="471" height="1024" src="https://blog.xojo.com/wp-content/uploads/2026/03/aztec-barcode-1-471x1024.png" alt="" class="wp-image-16007" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/aztec-barcode-1-471x1024.png 471w, https://blog.xojo.com/wp-content/uploads/2026/03/aztec-barcode-1-138x300.png 138w, https://blog.xojo.com/wp-content/uploads/2026/03/aztec-barcode-1.png 555w" sizes="auto, (max-width: 471px) 100vw, 471px" /></figure>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="471" height="1024" src="https://blog.xojo.com/wp-content/uploads/2026/03/datamatrix-barcode-1-471x1024.png" alt="" class="wp-image-16008" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/datamatrix-barcode-1-471x1024.png 471w, https://blog.xojo.com/wp-content/uploads/2026/03/datamatrix-barcode-1-138x300.png 138w, https://blog.xojo.com/wp-content/uploads/2026/03/datamatrix-barcode-1.png 555w" sizes="auto, (max-width: 471px) 100vw, 471px" /></figure>
</div>
</div>



<h2 class="wp-block-heading">Icons on WebButtons</h2>



<p><code>WebButton</code>&nbsp;now has an&nbsp;<code>Icon</code>&nbsp;property. You can assign any&nbsp;<code>WebPicture</code>&nbsp;to it, or use one of the Bootstrap icons that are already bundled with the framework. It&#8217;s a small addition, but it makes a noticeable difference when building action-heavy interfaces where a label alone doesn&#8217;t communicate enough at a glance.</p>



<p>Add a button into your project:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="690" src="https://blog.xojo.com/wp-content/uploads/2026/03/button-icon-ide-2-1024x690.png" alt="" class="wp-image-16001" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/button-icon-ide-2-1024x690.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/03/button-icon-ide-2-300x202.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/button-icon-ide-2-768x517.png 768w, https://blog.xojo.com/wp-content/uploads/2026/03/button-icon-ide-2-1536x1035.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/03/button-icon-ide-2-2048x1380.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Configure its Icon property in the <code>Opening</code> event:</p>



<pre class="wp-block-code"><code>Me.Icon = WebPicture.BootstrapIcon("key-fill")</code></pre>



<p>If you don&#8217;t specify a color in BootstrapIcon, it will inherit the button caption color in this case. This is the easiest way to support Dark Mode with the new <code>WebButton.Icon</code> property, without doing any special tricks.</p>



<p>Here is how it looks like at runtime:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="889" src="https://blog.xojo.com/wp-content/uploads/2026/03/button-browser-light-1024x889.png" alt="" class="wp-image-15999" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/button-browser-light-1024x889.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/03/button-browser-light-300x261.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/button-browser-light-768x667.png 768w, https://blog.xojo.com/wp-content/uploads/2026/03/button-browser-light-1536x1334.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/03/button-browser-light.png 1612w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Dark Mode:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="889" src="https://blog.xojo.com/wp-content/uploads/2026/03/button-browser-dark-1024x889.png" alt="" class="wp-image-16000" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/button-browser-dark-1024x889.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/03/button-browser-dark-300x261.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/button-browser-dark-768x667.png 768w, https://blog.xojo.com/wp-content/uploads/2026/03/button-browser-dark-1536x1334.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/03/button-browser-dark.png 1612w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading">WebLabel: Semantic HTML and Proper Element Types</h2>



<p>Two related changes landed for&nbsp;<code>WebLabel</code>&nbsp;in this release. The first is a correctness fix: the control was previously rendered using the HTML&nbsp;<code>&lt;label&gt;</code>&nbsp;element, which is semantically meant to label form inputs, not to display general text. That has been corrected.</p>



<p>The more interesting addition is that you can now choose which HTML element&nbsp;<code>WebLabel</code>&nbsp;renders as. If you want a label to be an&nbsp;<code>&lt;h1&gt;</code>&nbsp;or an&nbsp;<code>&lt;h2&gt;</code>, you can set that directly in the Inspector. This is useful not just for visual styling, but for accessibility tools and search engines that rely on page structure to understand content hierarchy.</p>



<p>Improving both, accessibility and making search engines happier, are some of our goals for 2026. You will continue seeing improvements in this sense.</p>



<h2 class="wp-block-heading">WebTextArea Gets AddText</h2>



<p><code>WebTextArea</code>&nbsp;now has an&nbsp;<code>AddText</code>&nbsp;method, consistent with how the control works on Desktop and Mobile. If you&#8217;re writing code that targets multiple platforms, this kind of parity saves you from having to check which target you&#8217;re on, before appending text.</p>



<h2 class="wp-block-heading">Scale Indicator on WebMapViewer</h2>



<p><code>WebMapViewer</code>&nbsp;now has a&nbsp;<code>HasScaleIndicator</code>&nbsp;property. When enabled, a small visual scale appears on the map showing real-world distance. It makes a difference in apps where users need spatial context. Field work, logistics or anything where &#8220;how far is that?&#8221; is a question users might actually ask.</p>



<h2 class="wp-block-heading">Performance and Modernization Under the Hood</h2>



<p>A few changes in this release won&#8217;t be immediately visible, but they improve things for everyone.</p>



<p>Bootstrap has been updated to v5.3.8 which fixes some issues introduced in v5.3.7 impacting Xojo. The TypeScript compiler has been updated to v5.9.3, and the compilation target has been bumped from ES6 to ES2020. Unused code in the Web Framework has been cleaned up to reduce the compiled bundle size.</p>



<p>Xojo has also removed its own internal usage of Modernizr. The library is still present for now so existing apps that rely on it won&#8217;t break, but it&#8217;s no longer used by the framework itself and will be removed in a future release.</p>



<p>If you&#8217;ve been meaning to audit your web app for performance, this is a good moment to look at&nbsp;<code>SendEventsInBatches</code>&nbsp;and&nbsp;<code>LazyLoadDependencies</code>&nbsp;on&nbsp;<code>WebSession</code>&nbsp;as well. Both now default to&nbsp;<code>True</code>&nbsp;on new projects, so if your existing app has them disabled, it&#8217;s worth trying them out. These properties have been around for a while already but were turned off by default.</p>



<h2 class="wp-block-heading">API Consistency Cleanups</h2>



<p>A few methods have been deprecated in favour of names that are consistent with the rest of the framework:</p>



<ul class="wp-block-list">
<li><code>WebApplication.AutoQuit</code>&nbsp;→&nbsp;<code>AllowAutoQuit</code></li>



<li><code>WebListBox.ReloadData</code>&nbsp;→&nbsp;<code>ReloadFromDataSource</code></li>



<li><code>WebRadioGroup.RemoveAllRows</code>&nbsp;→&nbsp;<code>RemoveAll</code>, and&nbsp;<code>RemoveRowAt</code>&nbsp;→&nbsp;<code>RemoveAt</code></li>
</ul>



<p>Your existing code will still compile, but it&#8217;s worth updating these when you get a chance.</p>



<h2 class="wp-block-heading">Wrapping Up</h2>



<p>Between new controls, better HTML semantics, and a leaner runtime, 2026r1 is a worthwhile update for anyone building web apps with Xojo. Check out the&nbsp;<a href="https://documentation.xojo.com/resources/release_notes/2026r1.html">full release notes</a>&nbsp;for the complete list of changes.</p>



<p><em>Ricardo has always been curious about how things work. Growing up surrounded by computers</em> he became interested in <em>web technologies in the dial-up connections era. Xojo has been his secret weapon and language of preference since 2018. When he’s not online, chances are he will be scuba diving … or crocheting amigurumis. Find Ricardo on Twitter <a href="https://web.archive.org/web/20220805000833/https://www.twitter.com/piradoiv" target="_blank" rel="noreferrer noopener">@piradoiv</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2026/03/colorpicker-browser.mp4" length="707463" type="video/mp4" />

			</item>
		<item>
		<title>Watchpoints in Xojo: A Smarter Way to Track Your Data</title>
		<link>https://blog.xojo.com/2026/03/31/watchpoints-in-xojo-a-smarter-way-to-track-your-data/</link>
		
		<dc:creator><![CDATA[William Yu]]></dc:creator>
		<pubDate>Tue, 31 Mar 2026 13:22:00 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[2026r1]]></category>
		<category><![CDATA[Debugging]]></category>
		<category><![CDATA[Watchpoints]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15987</guid>

					<description><![CDATA[Debugging isn’t just about stepping through code anymore, it&#8217;s about understanding how your data behaves over time. With the new watchpoints feature in Xojo, you can&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Debugging isn’t just about stepping through code anymore, it&#8217;s about understanding how your data behaves over time. With the new watchpoints feature in Xojo, you can now monitor variables and object properties more intelligently, without constantly stepping line by line or adding logging just to see when values change.</p>



<h3 class="wp-block-heading">What Are Watchpoints?</h3>



<p>Watchpoints let you pause execution when the value of a variable or property changes. Instead of asking <em>“how did I get here?”</em>, watchpoints help you answer <em>“when did this change?”</em></p>



<p>This is especially useful when:</p>



<ul class="wp-block-list">
<li>A value is being modified unexpectedly</li>



<li>Multiple parts of your code interact with the same object</li>



<li>You’re tracking down subtle state-related bugs</li>
</ul>



<h3 class="wp-block-heading">How Watchpoints Work</h3>



<p>Setting up a watchpoint requires pausing execution where you would like to start monitoring the variable or property of an object.</p>



<figure class="wp-block-image size-large is-style-default"><img loading="lazy" decoding="async" width="1024" height="677" src="https://blog.xojo.com/wp-content/uploads/2026/03/WatchpointSetupClipped-1024x677.jpg" alt="" class="wp-image-16018" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/WatchpointSetupClipped-1024x677.jpg 1024w, https://blog.xojo.com/wp-content/uploads/2026/03/WatchpointSetupClipped-300x198.jpg 300w, https://blog.xojo.com/wp-content/uploads/2026/03/WatchpointSetupClipped-768x508.jpg 768w, https://blog.xojo.com/wp-content/uploads/2026/03/WatchpointSetupClipped.jpg 1446w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>In this example, we want to monitor the <code>count</code> variable, so you can right-click it in the variables debugger list and select <strong>Watch</strong> from the context menu.  Once a watchpoint is set on a variable or property, the debugger keeps track of its value during execution. When the value changes, execution pauses and shows the line that triggered the change. Notice that the watchpoint break line is highlighted differently from the current execution line, and a Watchpoints list is now displayed.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="667" src="https://blog.xojo.com/wp-content/uploads/2026/03/WatchpointBreak-1024x667.png" alt="" class="wp-image-16014" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/WatchpointBreak-1024x667.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/03/WatchpointBreak-300x195.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/WatchpointBreak-768x500.png 768w, https://blog.xojo.com/wp-content/uploads/2026/03/WatchpointBreak-1536x1000.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/03/WatchpointBreak-2048x1333.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>This gives you immediate visibility into:</p>



<ul class="wp-block-list">
<li>What code caused the modification</li>



<li>What the previous and new values are</li>



<li>What the surrounding state looks like</li>
</ul>



<h3 class="wp-block-heading">Why This Matters</h3>



<p>Traditionally, tracking down a value change required manually stepping through code or adding temporary logging. Both approaches are time-consuming and error-prone.</p>



<p>Watchpoints eliminate that friction by:</p>



<ul class="wp-block-list">
<li>Reducing the need for repetitive stepping</li>



<li>Highlighting only meaningful changes</li>



<li>Letting you focus on the root cause faster</li>
</ul>



<h3 class="wp-block-heading">Conditional Watchpoints</h3>



<p>Watchpoints in Xojo aren&#8217;t limited to triggering on every change—you can make them conditional. For example, you can break only when a value is equal to, greater than, or less than a specific threshold, or even when it falls within a defined range. For string, both case-sensitive and case-insensitive comparisons are supported. This makes it much easier to focus on the changes that actually matter, especially when a variable updates frequently but only becomes problematic under certain conditions.</p>



<p>To add a condition to a watchpoint, right-click the watched variable or property and choose&nbsp;<strong>Edit Watchpoint Expression</strong> from the context menu.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="695" src="https://blog.xojo.com/wp-content/uploads/2026/03/WatchpointExpression-1024x695.png" alt="" class="wp-image-16020" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/WatchpointExpression-1024x695.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/03/WatchpointExpression-300x204.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/WatchpointExpression-768x522.png 768w, https://blog.xojo.com/wp-content/uploads/2026/03/WatchpointExpression.png 1496w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>The expression editor adapts based on the type of variable or property you&#8217;re watching, providing hints about what values and conditions you can enter.</p>



<h3 class="wp-block-heading">Handling Object Lifetimes</h3>



<p>One important detail when working with watchpoints is object lifetime.</p>



<p>If a watchpoint is attached to a property of an object that goes out of scope or is destroyed, the debugger can no longer track it. In these cases, Xojo provides feedback through the Messages pane so you know the watchpoint is no longer valid, along with the last known value.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="890" height="180" src="https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-24-at-9.33.52-AM.png" alt="" class="wp-image-16021" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-24-at-9.33.52-AM.png 890w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-24-at-9.33.52-AM-300x61.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-24-at-9.33.52-AM-768x155.png 768w" sizes="auto, (max-width: 890px) 100vw, 890px" /></figure>



<h3 class="wp-block-heading">What works and what doesn&#8217;t</h3>



<p>You can set watchpoints on most variables and properties, even variants; however, Arrays, Structures, and computed properties are not supported. Code within <code>#pragma DisableBackgroundTasks</code> or <code>#pragma Debug False</code> blocks will not trigger watchpoint breaks. Watchpoints are also not currently available for Android projects.</p>



<h3 class="wp-block-heading">Final Thoughts</h3>



<p>Watchpoints bring a new level of precision to debugging in Xojo. Instead of chasing bugs through code, you can now let the debugger do the work of tracking down exactly where things go wrong.</p>



<p>Give them a try in your next debugging session—you might find yourself solving problems faster than ever!</p>



<p><em><em><em>William Yu grew up in Canada learning to program BASIC on a Vic-20. He is Xojo’s resident Windows and Linux engineer, among his many other skills. Some may say he has joined the dark side here in the USA, but he will always be a Canadian at heart.</em></em></em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Team-based Signing Arrives to macOS</title>
		<link>https://blog.xojo.com/2026/03/31/team-based-signing-arrives-to-macos/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Tue, 31 Mar 2026 13:21:00 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[2026r1]]></category>
		<category><![CDATA[Apple Developer Account]]></category>
		<category><![CDATA[Code Signing]]></category>
		<category><![CDATA[Distribution]]></category>
		<category><![CDATA[macOS]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15951</guid>

					<description><![CDATA[In Xojo 2026r1 we revised the macOS Developer ID field and replaced it with a Team-based popup menu that aligns with the style found in&#8230;]]></description>
										<content:encoded><![CDATA[
<p>In Xojo 2026r1 we revised the macOS Developer ID field and replaced it with a Team-based popup menu that aligns with the style found in iOS projects. This change aims to offer a cleaner, more intuitive way to manage developer certificates for the distribution of your built macOS app.</p>



<span id="more-15951"></span>



<p>The Developer ID field was introduced in Xojo 2022r1, allowing you to fill in the developer certificate information needed for signing built macOS apps; however, it could be confusing to know exactly what information was expected.</p>



<ul class="wp-block-list">
<li>Developer ID Application</li>



<li>Developer ID Application: Francisco Javier Rodriguez Menendez</li>



<li>Developer ID Application: Francisco Javier Rodriguez Menendez (BW7PU32485)</li>



<li>7D767DB917A45A8976BEB5B92F04E8C18D09501A</li>
</ul>



<p>And… which certificate should be used for Development builds, Direct Distribution, or Mac App Store publishing? That may not be obvious for someone new to all this.</p>



<p>Additionally, what happens if the entered data comes from an expired certificate or if the certificate isn’t in the Keychain?</p>



<h2 class="wp-block-heading">The new approach: How it works</h2>



<p>The Team-based signing chooser for the Mac Developer ID field follows these steps:</p>



<ul class="wp-block-list">
<li><strong>Collects all the developer certificates</strong> found under the user Keychain.</li>



<li><strong>Groups the valid certificates by Team</strong> (what Apple designates as the TeamID).</li>



<li>Based on the previous information, the new popup menu &#8220;Build For&#8221; will offer only the code-signing options available for the current selected Team:
<ul class="wp-block-list">
<li><strong>Development</strong>. This is the equivalent to using the Apple Development certificate.</li>



<li><strong>Direct Distribution</strong>. This is the equivalent to using the Developer ID Application certificate.</li>



<li><strong>App Store</strong>. This is the equivalent to using the Apple Distribution certificate. In addition, the Publish feature will be enabled if, for the selected Team, there is also a valid 3rd‑party Mac Developer Installer certificate available.</li>
</ul>
</li>
</ul>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="600" height="540" src="https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-18-at-09.28.02.png" alt="" class="wp-image-15962" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-18-at-09.28.02.png 600w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-18-at-09.28.02-300x270.png 300w" sizes="auto, (max-width: 600px) 100vw, 600px" /></figure>
</div>


<p>If None is selected in the Developer ID popup menu, the macOS app will be built/debugged using Ad-Hoc signing.</p>



<p>Both menus update on the fly, so if new certificates are added (or removed) from the keychain, or if any have expired since last opened, both the Developer ID and Build For popup menus will reflect those changes.</p>



<h2 class="wp-block-heading">macOS Certificates Inspector Window</h2>



<p>Under the Teams popup menu, there is also an Inspect… option. When selected, it opens a new window where you can view and gather additional information for:</p>



<ul class="wp-block-list">
<li>Installed / Missing Apple Intermediate Certificates.</li>



<li>Installed / Missing / Expired Developer Certificates, grouped by Team.</li>
</ul>



<p>At a glance, you’ll see useful details for each certificate, such as:</p>



<ul class="wp-block-list">
<li>The expiration date</li>



<li>The keychain where it is stored.</li>



<li>Serial number, useful for identifying same-kind developer / intermediate certificates under different Macs.</li>



<li>Issuer specific information.</li>
</ul>



<p>Clicking any certificate provides more detailed information about the role it plays in the macOS signing process.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="2522" height="1920" src="https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-18-at-09.30.21.png" alt="" class="wp-image-15963" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-18-at-09.30.21.png 2522w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-18-at-09.30.21-300x228.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-18-at-09.30.21-1024x780.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-18-at-09.30.21-768x585.png 768w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-18-at-09.30.21-1536x1169.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/03/Screenshot-2026-03-18-at-09.30.21-2048x1559.png 2048w" sizes="auto, (max-width: 2522px) 100vw, 2522px" /></figure>
</div>


<p>This Inspector is also useful in order to identify some of the most common issues related with the handling of certificates such as:</p>



<ul class="wp-block-list">
<li><strong>Missing certificates for a given Team</strong>, determining thus the options that are available under the &#8220;Build For&#8221; popup menu.</li>



<li><strong>Expired certificates</strong>. These also determine the options that are available under the &#8220;Build For&#8221; popup menu for a given Team. In addition, if you want to do some cleanup, it is possible to delete these expired certificates directly from the Inspector without needing to open the Keychain Access app.</li>



<li><strong>About to expire certificates</strong>, so you are aware of it and the impact it could have on apps close to be distributed or on already created Provisioning Profiles, for example.</li>



<li><strong>Certificates with their private key missing</strong>. These can&#8217;t be used for signing purposes, so you will be able to re-install them in the keychain (if you have a backup) or install a new certificate.</li>



<li><strong>Developer Certificates where some of the required intermediate certificate is missing</strong>. You will be able to install the missing Intermediate (active Internet connection required).</li>
</ul>



<h2 class="wp-block-heading">Improvements to macOS Builds and Debugged apps</h2>



<p>Although Sandboxing, Entitlements, and Provisioning Profiles have been part of macOS app development, this release brings several enhancements in these areas:</p>



<ul class="wp-block-list">
<li>Now it is possible <strong>debug Sandboxed apps</strong> directly from the IDE.</li>



<li><strong>Entitlements and Provisioning Profile</strong> are applied when the app is debugged from the IDE.</li>



<li>Improvements in how the required Entitlements are added and signed when the macOS app is built; and also a better handling of the user-added entitlements and provisioning profile files (if required).</li>



<li><strong>Debugged and Built apps can be attached to the Instruments app</strong>. Among other things, Instruments can be used to detect issues such as memory leaks in the executed app. The IDE now automatically adds the required entitlement for this when: the app is debugged/built using the &#8220;None&#8221; (Ad-Hoc signing) from the Team popup menu, or, 2) when the app is built for Development (Build For) for a given Team.</li>
</ul>



<figure class="wp-block-video"><video controls src="https://blog.xojo.com/wp-content/uploads/2026/03/Untitled.mp4"></video></figure>



<p>When Build For is set to Direct Distribution or App Store, the required entitlement for Instruments to attach to the app, will be added only when the app is debugged from the IDE. If you want to use Instruments with a built app signed using these certificates, then you need to add that entitlement explicitly.</p>



<p>This decision is because when get-tasks-allow is set to True (the entitlement required in order Instrument being able to function), there are some well documented vulnerabilities that could be used to escalate privileges or inject code into your app. That&#8217;s not desirable for your distributed apps for sure (whether using Direct Distribution or if your app is installed through the Mac App Store).</p>



<h2 class="wp-block-heading">Looking forward</h2>



<p><br>We know there are still some areas to improve regarding code signing on macOS (and iOS) and we are working on some of them already. In the meantime, you’ll likely find the new Team-based Developer ID option more approachable, especially if this is your first experience dealing with certificates, signing, and distributing your freshly built macOS app.</p>



<p>A big THANK YOU to Richard Grafl for all his help and feedback during the beta-testing cycle of this feature.</p>



<p>Happy macOS code-signing!</p>



<p><em>Javier Menendez is an engineer at Xojo and has been using Xojo since 1998. He lives in Castellón</em>, <em>Spain and hosts regular Xojo hangouts en español. Ask Javier questions on Twitter at <a href="https://twitter.com/xojoes" target="_blank" rel="noreferrer noopener">@XojoES</a> or on the <a href="https://forum.xojo.com/u/javier_menendez/summary" target="_blank" rel="noreferrer noopener">Xojo Forum</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p>Learn more about Code Signing in our recent series:</p>



<p><strong>Code Signing on macOS: What Developers Need to Know</strong></p>



<ul class="wp-block-list">
<li><a href="https://blog.xojo.com/2026/03/04/code-signing-on-macos-what-developers-need-to-know-part-1/" target="_blank" rel="noreferrer noopener">Part 1, Get Started</a></li>



<li><a href="https://blog.xojo.com/2026/03/18/code-signing-on-macos-what-developers-need-to-know-part-2/" target="_blank" rel="noreferrer noopener">Part 2, Code Signing With Developer Certificates</a></li>



<li><a href="https://blog.xojo.com/2026/03/24/code-signing-on-macos-what-developers-need-to-know-part-3/">Part 3, Entitlements and Provisioning Profiles</a></li>



<li><a href="https://blog.xojo.com/2026/04/07/code-signing-on-macos-what-developers-need-to-know-part-4/" target="_blank" rel="noreferrer noopener">Part 4, How Xojo helps with Certificates, Signing and Distribution</a></li>
</ul>
]]></content:encoded>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2026/03/Untitled.mp4" length="2577230" type="video/mp4" />

			</item>
		<item>
		<title>Code Signing on macOS: What Developers Need to Know, Part 3</title>
		<link>https://blog.xojo.com/2026/03/24/code-signing-on-macos-what-developers-need-to-know-part-3/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Tue, 24 Mar 2026 16:00:00 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Apple Developer Account]]></category>
		<category><![CDATA[Code Signing]]></category>
		<category><![CDATA[Distribution]]></category>
		<category><![CDATA[macOS]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15944</guid>

					<description><![CDATA[If you followed the previous two articles in this series, you should be set up properly now, right? Your Mac developer certificates are stored in&#8230;]]></description>
										<content:encoded><![CDATA[
<p>If you followed the previous two articles in this series, you should be set up properly now, right? Your Mac developer certificates are stored in Keychain Access, so you only need to fill in the Developer ID field under Build Settings &gt; macOS &gt; Sign with the appropriate certificate value, click Build (or Publish), and distribute your new amazing app worldwide. Well, not quite. There are still other pieces to consider when signing and distributing your macOS app.</p>



<span id="more-15944"></span>



<p>For the past 20 years, Apple has increasingly tightened security measures when it comes to running apps distributed by third parties. Let&#8217;s take a look at this summarized timeline of code-signing and security measures added by Apple over years:</p>


<div class="wp-block-image">
<figure class="aligncenter"><a href="https://blog.xojo.com/wp-content/uploads/2026/03/macOS-signing-Timeline-scaled.png"><img loading="lazy" decoding="async" width="2560" height="1056" src="https://blog.xojo.com/wp-content/uploads/2026/03/macOS-signing-Timeline-scaled.png" alt="" class="wp-image-15945" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/macOS-signing-Timeline-scaled.png 2560w, https://blog.xojo.com/wp-content/uploads/2026/03/macOS-signing-Timeline-300x124.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/macOS-signing-Timeline-1024x422.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/03/macOS-signing-Timeline-768x317.png 768w, https://blog.xojo.com/wp-content/uploads/2026/03/macOS-signing-Timeline-1536x634.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/03/macOS-signing-Timeline-2048x845.png 2048w" sizes="auto, (max-width: 2560px) 100vw, 2560px" /></a></figure>
</div>


<p>The most notable developments happened in 2011, 2012 and 2018, when terms like Sandbox and, especially, Containers, Gatekeeper, Hardened Runtime and Notarization were introduced and began to impact other pieces of the puzzle to consider when signing macOS apps. In fact, we could say that technologies such as code-signing, Sandboxing, Entitlements or Provisioning Profiles were among the first iOS technologies to make their way to macOS.</p>



<p>So here is an broad overview what these technologies mean:</p>



<ul class="wp-block-list">
<li><strong>Sandboxing</strong>&#8211; When used, Sandboxing confines applications to a restricted, designated area of the system (its own &#8220;container&#8221;), preventing them from accessing user data, hardware or other apps without explicit permission. The system requires apps to ask for permission to use hardware resources or access user files. Sandboxing is mandatory for apps distributed through the Mac App Store.</li>



<li><strong>Gatekeeper-</strong> This technology is the primary security layer that checks whether a downloaded app comes from a verified/known developer, especially when the application has been Notarized by Apple.</li>



<li><strong>Hardened Runtime</strong>&#8211; Acts as a proactive, system-enforced shield that protects applications while they run, preventing malicious code from exploiting legitimate software. Enabling Hardened Runtime is required for Notarization.</li>



<li><strong>Notarization</strong>&#8211; Notarization is an automated security screening process run by Apple that scans software distributed outside the Mac App Store for malicious components and known security issues. Today, notarization is required for software distributed outside the Mac App Store that has been signed with the Developer ID application certificate. As a result of the process, notarization generates and staples a ticket, signed by an Apple certificate, to the app so Gatekeeper can trust it when executed.</li>
</ul>



<p>So, basically, while Sandboxing is still optional for apps distributed outside the Mac App Store (i.e., signed with your Developer ID certificate), Notarization and Hardened Runtime are the recommended defaults. Enabling Sandboxing for your app is something you should consider based on the needs (features) and the privacy balance you want to offer your users.</p>



<p>If you plan to distribute the app through the Mac App Store as well, it will need to be Sandboxed and signed with your Apple Distribution certificate, while enabling Hardened Runtime is optional.</p>



<h2 class="wp-block-heading">Entitlements and Provisioning Profiles</h2>



<p>Entitlements and Provisioning Profiles are also required for many of these security measures, depending on the features and services your app uses, and they come into play during building and signing.</p>



<p>If you decide to go the Sandboxing route, then using Entitlements is mandatory. The good news is that Sandboxing entitlements are free to use (they don’t require creating or adding a Provisioning Profile to the project). However, if your app needs special access to the Keychain or uses iCloud, Apple Pay, or other services, you’ll need to create a Provisioning Profile in the Apple Developer portal.</p>



<p>Wait—what are Entitlements and Provisioning Profiles, and how do they relate to macOS app code signing?</p>



<h3 class="wp-block-heading">Entitlements</h3>



<p>Entitlements are XML-based .plist files (not unlike the app’s Info.plist) containing a set of key-value pairs. They are embedded directly into the app’s binary as part of the code signing process, typically using your Developer ID Application or Apple Distribution certificates.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="931" height="651" src="https://blog.xojo.com/wp-content/uploads/2026/03/Entitlements.png" alt="" class="wp-image-15946" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/Entitlements.png 931w, https://blog.xojo.com/wp-content/uploads/2026/03/Entitlements-300x210.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/Entitlements-768x537.png 768w" sizes="auto, (max-width: 931px) 100vw, 931px" /></figure>



<h3 class="wp-block-heading">Provisioning Profiles</h3>



<p>While Entitlements are just a file, Provisioning Profiles are a different beast:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="911" height="514" src="https://blog.xojo.com/wp-content/uploads/2026/03/Provisioning-Profiles.png" alt="" class="wp-image-15947" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/Provisioning-Profiles.png 911w, https://blog.xojo.com/wp-content/uploads/2026/03/Provisioning-Profiles-300x169.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/Provisioning-Profiles-768x433.png 768w" sizes="auto, (max-width: 911px) 100vw, 911px" /></figure>



<p>Provisioning Profiles must be created in the Apple Developer Portal. When you create one, you specify the App ID (the combination of your Team ID and the app bundle identifier which are case sensitive so pay attention). Even if you don’t plan to distribute your macOS app via the Mac App Store, you still need a Provisioning Profile, which requires creating an App ID first in the Developer Portal.</p>



<p>There are two kinds of Provisioning Profiles: Development and Distribution. As part of the provisioning profile creation, you must choose which type you will use.</p>



<ul class="wp-block-list">
<li><strong>Development Provisioning Profiles</strong> are used while you’re developing your app; the app is signed with an Apple Development certificate and is intended to run on a set of Mac computers you’ve registered. During creation, you can add as many Apple Development certificates as you have under your Team ID.</li>



<li><strong>Distribution Provisioning Profiles</strong> are used when distributing your app. For direct distribution, sign with the same Developer ID certificate you’ll use for signing the app; for Mac App Store distribution, sign with the Apple Distribution certificate.</li>



<li><strong>Development and Distribution Provisioning Profiles do expire</strong>. This is something to keep in mind, especially when deploying new or updated versions of your app, because you may need to create new profiles.</li>



<li><strong>Development and Distribution Profiles are editable</strong>. If you make a mistake, note that both types can be edited in the Apple Developer portal, but only for certain fields: the App ID, the profile name, the selected certificate, and (for Development profiles) the included testing devices.</li>
</ul>



<h2 class="wp-block-heading">When Certificates and/or Provisioning Profiles expire…</h2>



<p>We’ve already noted in previous articles that Apple Developer certificates expire one year after they’re created. We’ve also learned that if your app relies on a Distribution Provisioning Profile, that profile can expire as well. So, what does this mean for your already deployed apps?</p>



<p>No worries. Let’s focus first on directly distributed macOS apps (those signed with the Developer ID certificate) and pull one screenshot from the previous article:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1740" height="882" src="https://blog.xojo.com/wp-content/uploads/2026/03/Timestamp.png" alt="" class="wp-image-15948" srcset="https://blog.xojo.com/wp-content/uploads/2026/03/Timestamp.png 1740w, https://blog.xojo.com/wp-content/uploads/2026/03/Timestamp-300x152.png 300w, https://blog.xojo.com/wp-content/uploads/2026/03/Timestamp-1024x519.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/03/Timestamp-768x389.png 768w, https://blog.xojo.com/wp-content/uploads/2026/03/Timestamp-1536x779.png 1536w" sizes="auto, (max-width: 1740px) 100vw, 1740px" /></figure>



<p>Observe the highlighted Timestamp line. When the app is signed, the date is added automatically (retrieved from Apple’s servers). So, when a user runs an app whose embedded Developer ID Certificate has expired since its release, Gatekeeper will rely on that timestamp, compare it to the embedded certificate’s expiration date, and if everything matches—meaning it was signed before the certificate expired—the app will continue to work, provided the embedded certificate has not been revoked by the developer. In addition, if the app was Notarized, that helps a lot, because the stapled ticket includes its own timestamp and was signed with a longer-lasting Apple Certificate.</p>



<p>If the app is distributed through the Mac App Store, there’s good news. After you submit the app for distribution via App Store Connect and it passes Apple’s review, the app’s signing with your Apple Distribution certificate is replaced by Apple’s own signing. This means that users who install the app from the Mac App Store can continue to run it even if your original Apple Distribution certificate expired long ago.</p>



<p>Distribution Provisioning Profiles behave differently from others: once they expire, the app containing such a Distribution Profile will fail to execute.</p>



<p>The good news is that a Distribution Profile lasts for a very long time (around 18 years) so you’ll likely have ample time to create new distribution provisioning profiles and deploy updates that use renewed profiles well before users are affected.</p>



<p>Of course, as soon as any of your Apple Developer certificates expire, you already know how to request and install new ones in your Mac keychain.</p>



<h2 class="wp-block-heading">Nearly Concluded</h2>



<p>In the next, and last article, we will see how Xojo helps with everything related to signing and distributing your macOS apps. I&#8217;ll also show you how to deal with some of the most common issues related with certificates.</p>



<p><em>Javier Menendez is an engineer at Xojo and has been using Xojo since 1998. He lives in Castellón</em>, <em>Spain and hosts regular Xojo hangouts en español. Ask Javier questions on Twitter at <a href="https://twitter.com/xojoes" target="_blank" rel="noreferrer noopener">@XojoES</a> or on the <a href="https://forum.xojo.com/u/javier_menendez/summary" target="_blank" rel="noreferrer noopener">Xojo Forum</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p><strong>Code Signing on macOS: What Developers Need to Know</strong></p>



<ul class="wp-block-list">
<li><a href="https://blog.xojo.com/2026/03/04/code-signing-on-macos-what-developers-need-to-know-part-1/" target="_blank" rel="noreferrer noopener">Part 1, Get Started</a></li>



<li><a href="https://blog.xojo.com/2026/03/18/code-signing-on-macos-what-developers-need-to-know-part-2/" target="_blank" rel="noreferrer noopener">Part 2, Code Signing With Developer Certificates</a></li>



<li><a href="https://blog.xojo.com/2026/03/24/code-signing-on-macos-what-developers-need-to-know-part-3/">Part 3, Entitlements and Provisioning Profiles</a></li>



<li><a href="https://blog.xojo.com/2026/04/07/code-signing-on-macos-what-developers-need-to-know-part-4/" target="_blank" rel="noreferrer noopener">Part 4, How Xojo helps with Certificates, Signing and Distribution</a></li>
</ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Code Signing on macOS: What Developers Need to Know, Part 2</title>
		<link>https://blog.xojo.com/2026/03/18/code-signing-on-macos-what-developers-need-to-know-part-2/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Wed, 18 Mar 2026 14:00:00 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Apple Developer Account]]></category>
		<category><![CDATA[Code Signing]]></category>
		<category><![CDATA[Distribution]]></category>
		<category><![CDATA[macOS]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15864</guid>

					<description><![CDATA[On the Apple side of code signing with developer certificates, we already know that the required root certificate, acting as the base anchor of the&#8230;]]></description>
										<content:encoded><![CDATA[
<p>On the Apple side of code signing with developer certificates, we already know that the required root certificate, acting as the base anchor of the trust chain, is installed already on our Macs under the System Roots keychain.</p>



<p>But before we can reach our leaf developer certificates,&nbsp;we also need to have the Apple Development Intermediate certificates installed in our keychain. These are typically found in the Login keychain, though they can also be found in the System Roots or System keychains.</p>



<h2 class="wp-block-heading">Installing Apple Developer Intermediate Certificates</h2>



<p>Since Xcode 11.4.1 and later, these can be automatically downloaded and installed in the keychain, but if not, they can also can be downloaded from the <a href="https://www.apple.com/certificateauthority/" target="_blank" rel="noreferrer noopener">Apple PKI</a> webpage. The ones we are interested in are:</p>



<ul class="wp-block-list">
<li>Developer ID &#8211; G2</li>



<li>Worldwide Developer Relations &#8211; G2</li>



<li>Worldwide Developer Relations &#8211; G3</li>



<li>Worldwide Developer Relations &#8211; G4</li>



<li>Worldwide Developer Relations &#8211; G5</li>



<li>Worldwide Developer Relations &#8211; G6</li>
</ul>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Note: The Developer ID &#8211; G2 certificate corresponds to the Developer ID Certification Authority. The WWDR certificates (G2–G6) correspond to the Apple Worldwide Developer Relations Certification Authority.</p>
</blockquote>



<p>As you can see from the list, there are several versions (or generations) for the WWDR Intermediate certificate; so, which one should you download? The short answer: it depends.</p>



<p>On February, 7, 2023 the previous WWDR intermediate certificate expired; so Apple decided to rollout a new renewed version that will expire on February 20, 2030. As part of that update Apple issued additional Intermediate certificates to better segment the purpose of different certificates:</p>



<ul class="wp-block-list">
<li>G2: ECDSA signing for Apple Pay.</li>



<li>G3: Software signing and Services.</li>



<li>G4: Features supported by Apple Push Notification Service.</li>



<li>G5: App Store Signing and Services.</li>



<li>G6: ECDSA signing of Software and Services.</li>
</ul>



<p>In practice, G3, G4, and G5 are sufficient for most scenarios.</p>



<h2 class="wp-block-heading">Developer Certificates: The final goal!</h2>



<p>To focus on the subject, what kind of leaf developer certificates are created from these two types of Intermediate certificates? This scheme will help:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1644" height="912" src="https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Development-Certificates-Chain-Of-Trust.png" alt="" class="wp-image-15865" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Development-Certificates-Chain-Of-Trust.png 1644w, https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Development-Certificates-Chain-Of-Trust-300x166.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Development-Certificates-Chain-Of-Trust-1024x568.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Development-Certificates-Chain-Of-Trust-768x426.png 768w, https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Development-Certificates-Chain-Of-Trust-1536x852.png 1536w" sizes="auto, (max-width: 1644px) 100vw, 1644px" /></figure>



<p>As you can see from the above diagram, there are four main leaf certificates we will use to sign our macOS apps, based on their prefix:</p>



<ul class="wp-block-list">
<li><strong>Developer ID Application</strong>. Use this one to code sign a macOS app distributed outside the Mac App Store.</li>



<li><strong>Developer ID Installer</strong>. Use this one to code sign the Installer, DMG or .pgk file of a macOS app distributed outside the Mac App Store.</li>



<li><strong>Apple Distribution</strong>. This certificate is required to code sign a macOS app sent to the AppStore Connect for its distribution through the Mac App Store.</li>



<li><strong>3rd Party Mac Developer Installer</strong>. This Certificate is required to code sign the package of the app sent to the AppStore Connect. For example, when using the Publish feature from the Xojo IDE.</li>
</ul>



<h2 class="wp-block-heading">Creating and Installing the Developer Certificates</h2>



<p>As stated in the <a href="https://blog.xojo.com/2026/03/04/code-signing-on-macos-what-developers-need-to-know-part-1/" target="_blank" rel="noreferrer noopener">first article</a> of this series, you need a paid Apple Developer Program membership. Once that’s in place, the easiest way to install these required certificates in your macOS Keychain is through Xcode.</p>



<p>So, if it is the first time you need to install them on a Mac computer:</p>



<ol class="wp-block-list">
<li>Go to Xcode &gt; Preferences.</li>



<li>Select Apple Accounts.</li>



<li>Use your developer credentials to login into your developer account, or select it from the list if you are already logged.</li>



<li>Select the Team from the list.</li>



<li>Click the &#8220;Manage Certificates…&#8221; button.</li>



<li>Click the &#8220;+&#8221; popup menu in the lower-left corner of the resulting window, and select the developer certificate you want to install (all of these if it is the first time you install them).</li>
</ol>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="468" height="398" src="https://blog.xojo.com/wp-content/uploads/2026/02/Captura-de-pantalla-2026-02-25-a-las-15.53.00.png" alt="" class="wp-image-15866" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/Captura-de-pantalla-2026-02-25-a-las-15.53.00.png 468w, https://blog.xojo.com/wp-content/uploads/2026/02/Captura-de-pantalla-2026-02-25-a-las-15.53.00-300x255.png 300w" sizes="auto, (max-width: 468px) 100vw, 468px" /></figure>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>Note:</strong> Under the hood, Xcode follows the same process described for installing the developer certificates manually.</p>
</blockquote>



<p>If you prefer to go through the manual process instead:</p>



<ol class="wp-block-list">
<li>Access the <a href="https://developer.apple.com" target="_blank" rel="noreferrer noopener">Apple Developer website</a>.</li>



<li>In <a href="https://developer.apple.com/account/resources" target="_blank" rel="noreferrer noopener">Certificates, Identifiers &amp; Profiles, click Certificates in the sidebar.</a></li>



<li>On the top left, click the add button (+).</li>



<li>Under Software, select Developer ID, then click Continue.
<ul class="wp-block-list">
<li><strong>Developer ID Application</strong>: This certificate is used to code sign your app for distribution outside of the Mac App Store Connect.</li>



<li><strong>Developer ID Installer</strong>: This certificate is used to sign your app’s installer Package for distribution outside of the Mac App Store Connect.</li>



<li><strong>Apple Development</strong>: Used to run and debug apps on macOS during development.</li>



<li><strong>Apple Distribution</strong>: Used to sign apps for submission to App Store Connect.</li>



<li><strong>Mac App Distribution</strong>: Used to sign macOS apps intended to be distributed through the Mac App Store.</li>



<li><strong>Mac Installer Distribution</strong>: Used to send the macOS app to the App Store Connect for TestFlight or distribution through the Mac App Store.</li>
</ul>
</li>



<li>Follow the instructions to <a href="https://developer.apple.com/help/account/certificates/create-a-certificate-signing-request" target="_blank" rel="noreferrer noopener">create a certificate signing request</a>.</li>



<li>Click Choose File.</li>



<li>In the dialog that appears, select the certificate request file (a file with a .certSigningRequest file extension), then click Choose.</li>



<li>Click Continue.</li>



<li>Click Download.</li>



<li>The certificate file (a file with a .cer file extension) appears in your Downloads folder.</li>



<li>To install the certificate in your keychain, double-click the downloaded certificate file. The certificate appears in the My Certificates category in Keychain Access.</li>
</ol>



<h2 class="wp-block-heading">It&#8217;s All About Identities</h2>



<p>While Intermediate and Root certificates only have the Public Key on them, so they can verify other (leaf) certificates, the leaf certificates installed on your macOS Login keychain behave a bit different. Let&#8217;s see how.</p>



<p>Both if you use Xcode or create the CSR request manually to generate the developer certificates, using the Keychain Access app for that, in both of these scenarios <strong>a Private Key will be created and stored locally on your keychain</strong> as part of the process. <strong>Only the public key section of that private key is sent to the Apple servers</strong> so it can be included in the generated developer certificate. Once any of the possible developer certificates is downloaded and installed in the keychain, such certificate will have its private key associated with it:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="872" height="88" src="https://blog.xojo.com/wp-content/uploads/2026/02/Screenshot-2026-02-25-at-4.20.45-PM.png" alt="" class="wp-image-15867" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/Screenshot-2026-02-25-at-4.20.45-PM.png 872w, https://blog.xojo.com/wp-content/uploads/2026/02/Screenshot-2026-02-25-at-4.20.45-PM-300x30.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/Screenshot-2026-02-25-at-4.20.45-PM-768x78.png 768w" sizes="auto, (max-width: 872px) 100vw, 872px" /></figure>



<p>The pair of the developer certificate and the associated private key is what is called an Identity.</p>



<h2 class="wp-block-heading">Code signing With Developer Certificates</h2>



<p>In fact, while we often say or hear “code signing with certificates,” the real signing of the app is done with the private key associated with that certificate. The certificate itself (and thus the public key portion of that key pair) is included in the signing process. This allows macOS to verify the signature each time the user runs the app</p>



<p>Do you remember the diagram showing how the &#8220;Ad-Hoc&#8221; code signing process works? Let&#8217;s compare it when the same process is done using a &#8220;Developer ID Application&#8221; Certificate… and, most important, the associated private key:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1724" height="812" src="https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Certificate-Signing.png" alt="" class="wp-image-15869" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Certificate-Signing.png 1724w, https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Certificate-Signing-300x141.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Certificate-Signing-1024x482.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Certificate-Signing-768x362.png 768w, https://blog.xojo.com/wp-content/uploads/2026/02/Apple-Certificate-Signing-1536x723.png 1536w" sizes="auto, (max-width: 1724px) 100vw, 1724px" /></figure>



<p>As you can see, in this case the data is cyphered using the private key from the developer certificate and, then, the certificate itself is stored as part of the app itself. So, if for example we build this time an empty Desktop app for macOS using the Developer ID Application, and open the resulting CodeResources file in a text editor we will see something different compared with the Ad-Hoc signed version:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1298" height="974" src="https://blog.xojo.com/wp-content/uploads/2026/02/CodeResources_Signed.png" alt="" class="wp-image-15870" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/CodeResources_Signed.png 1298w, https://blog.xojo.com/wp-content/uploads/2026/02/CodeResources_Signed-300x225.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/CodeResources_Signed-1024x768.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/CodeResources_Signed-768x576.png 768w" sizes="auto, (max-width: 1298px) 100vw, 1298px" /></figure>



<p>In this case the field <strong>requirement&nbsp;</strong>associated with each file and hash value is significantly more strict. In fact, it makes reference to the Chain of Trust Gatekeeper is required to follow and validate. In plain English, the highlighted lines come to say something like:</p>



<ol class="wp-block-list">
<li>Hey! make sure there is a <strong>Developer ID Application</strong> certificate (Apple Extension attribute —OID— <em>1.2.840.113635.100.6.1.13&nbsp;</em>for the X.509 certificate), for the developer with a <strong>TeamID</strong> BW7PU32485.</li>



<li>Next, verify such certificate is issued by the &#8220;<strong>Apple Developer ID Certificate Authority</strong>&#8221; (other of the Apple-specific X.509 extension, attribute or OID. In this case: 1.2.840.113635.100.6.2.6).</li>



<li>And finally, go down through the Chain of Trust and verify the previous one with the <strong>Anchor</strong> certificate (Apple Root CA, do you remember?)</li>
</ol>



<p>So far so good. But how we can know if the app meets these requirements; and what about the certificates themselves? Well, it&#8217;s easy to check both using the codesign tool.</p>



<p>Open a Terminal window and type the following command:</p>



<pre class="wp-block-preformatted">codesign --verify -vvv "MyApp.app"</pre>



<p>The output will be something similar to this:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="2198" height="336" src="https://blog.xojo.com/wp-content/uploads/2026/02/codesign-SatisfiedRequirement.png" alt="" class="wp-image-15871" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/codesign-SatisfiedRequirement.png 2198w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-SatisfiedRequirement-300x46.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-SatisfiedRequirement-1024x157.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-SatisfiedRequirement-768x117.png 768w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-SatisfiedRequirement-1536x235.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-SatisfiedRequirement-2048x313.png 2048w" sizes="auto, (max-width: 2198px) 100vw, 2198px" /></figure>



<p>As you can see in the highlighted lines, yes, it satisfies the <strong>Designated Requirements</strong> we saw in our CodeResources file! Also, the previous line states that it is valid on disk. That means:</p>



<ul class="wp-block-list">
<li>All of the expected files are present.</li>



<li>There are no extra files.</li>



<li>None of the files have been modified.</li>



<li>A basic trust evaluation of the leaf certificate was successful.</li>



<li>And it satisfies its own Designated Requirements (DR).</li>
</ul>



<p>It is even possible to see the Chain of Trust for the code signature issuing:</p>



<pre class="wp-block-preformatted">codesign --display -vv "MyApp.app"&nbsp;</pre>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1222" height="340" src="https://blog.xojo.com/wp-content/uploads/2026/02/Codesign-ChainOfTrust.png" alt="" class="wp-image-15872" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/Codesign-ChainOfTrust.png 1222w, https://blog.xojo.com/wp-content/uploads/2026/02/Codesign-ChainOfTrust-300x83.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/Codesign-ChainOfTrust-1024x285.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/Codesign-ChainOfTrust-768x214.png 768w" sizes="auto, (max-width: 1222px) 100vw, 1222px" /></figure>



<p>And if you are curious enough, it is even possible to extract the embedded certificates stored in the <a href="https://www.ietf.org/rfc/rfc3852.txt" target="_blank" rel="noreferrer noopener">CMS structure within the code signature</a>:</p>



<pre class="wp-block-preformatted">codesign --display --extract-certificates "MyApp.app"</pre>



<p>As result it will, usually, create three files. Take a closer look at the &#8220;Issuer&#8221; and &#8220;Subject&#8221; lines; specially on the Subject line for the OU value (Organizative Unit or, using Apple wording, the TeamID) for the codesign0 file. Do you remember the &#8220;leaf[subject.OU=BW7PU32485]&#8221; data from the CodeResources file?&nbsp;:</p>



<p><strong>codesign0.</strong> This is the file for the Leaf certificate; in our example &#8220;Developer ID Application&#8221;.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1820" height="368" src="https://blog.xojo.com/wp-content/uploads/2026/02/codesign-DeveloperIDCertificate.png" alt="" class="wp-image-15873" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/codesign-DeveloperIDCertificate.png 1820w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-DeveloperIDCertificate-300x61.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-DeveloperIDCertificate-1024x207.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-DeveloperIDCertificate-768x155.png 768w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-DeveloperIDCertificate-1536x311.png 1536w" sizes="auto, (max-width: 1820px) 100vw, 1820px" /></figure>



<p><strong>codesign1.</strong> This one is for the Intermediate Certificate; in our example &#8220;Apple Developer ID Certificate Authority&#8221;.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1562" height="366" src="https://blog.xojo.com/wp-content/uploads/2026/02/codesign-IntermediateCertificate.png" alt="" class="wp-image-15874" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/codesign-IntermediateCertificate.png 1562w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-IntermediateCertificate-300x70.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-IntermediateCertificate-1024x240.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-IntermediateCertificate-768x180.png 768w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-IntermediateCertificate-1536x360.png 1536w" sizes="auto, (max-width: 1562px) 100vw, 1562px" /></figure>



<p><strong>codesign2.</strong> This one is for the Anchor Certificate; in our example &#8220;Apple Root CA&#8221;</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1274" height="344" src="https://blog.xojo.com/wp-content/uploads/2026/02/codesign-RootCertificate.png" alt="" class="wp-image-15875" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/codesign-RootCertificate.png 1274w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-RootCertificate-300x81.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-RootCertificate-1024x276.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/codesign-RootCertificate-768x207.png 768w" sizes="auto, (max-width: 1274px) 100vw, 1274px" /></figure>



<p><br>As shown by the <strong>Issuer</strong> line in the codesign0 file for our “Developer ID Application,” it points to the previous certificate in the trust chain—the Developer ID Certification Authority. The codesign1 file for the extracted Developer ID Certification Authority points to the Apple Certification Authority in its Issuer field. Finally, the codesign1 certificate points to itself because, as the Root Certificate, it serves as the <strong>anchor</strong> for the trust chain.</p>



<h2 class="wp-block-heading">Wrapping up</h2>



<p>In this second article, we delved deeper into how Apple Developer certificates work, how a macOS app is signed (Ad-Hoc or with a specific developer certificate), and how the OS’s security features validate the signing when a user tries to run the app.</p>



<p>In the next article, we will cover more details about signing apps for the two main distribution types: Direct distribution and Mac App Store. We will also discuss what happens when certificates expire and how to troubleshoot the most common issues related to development certificates.</p>



<p><em>Javier Menendez is an engineer at Xojo and has been using Xojo since 1998. He lives in Castellón</em>, <em>Spain and hosts regular Xojo hangouts en español. Ask Javier questions on Twitter at <a href="https://twitter.com/xojoes" target="_blank" rel="noreferrer noopener">@XojoES</a> or on the <a href="https://forum.xojo.com/u/javier_menendez/summary" target="_blank" rel="noreferrer noopener">Xojo Forum</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p><strong>Code Signing on macOS: What Developers Need to Know</strong></p>



<ul class="wp-block-list">
<li><a href="https://blog.xojo.com/2026/03/04/code-signing-on-macos-what-developers-need-to-know-part-1/" target="_blank" rel="noreferrer noopener">Part 1, Get Started</a></li>



<li><a href="https://blog.xojo.com/2026/03/18/code-signing-on-macos-what-developers-need-to-know-part-2/" target="_blank" rel="noreferrer noopener">Part 2, Code Signing With Developer Certificates</a></li>



<li><a href="https://blog.xojo.com/2026/03/24/code-signing-on-macos-what-developers-need-to-know-part-3/">Part 3, Entitlements and Provisioning Profiles</a></li>



<li><a href="https://blog.xojo.com/2026/04/07/code-signing-on-macos-what-developers-need-to-know-part-4/" target="_blank" rel="noreferrer noopener">Part 4, How Xojo helps with Certificates, Signing and Distribution</a></li>
</ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Code Signing on macOS: What Developers Need to Know, Part 1</title>
		<link>https://blog.xojo.com/2026/03/04/code-signing-on-macos-what-developers-need-to-know-part-1/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Wed, 04 Mar 2026 16:00:00 +0000</pubDate>
				<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Apple Developer Account]]></category>
		<category><![CDATA[Code Signing]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Distribution]]></category>
		<category><![CDATA[macOS]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15856</guid>

					<description><![CDATA[Your macOS app is finished and ready to go. But unless you plan to run it only on your own machine, there’s one essential step&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Your macOS app is finished and ready to go. But unless you plan to run it only on your own machine, there’s one essential step before sharing it with others: code signing with certificates.</p>



<span id="more-15856"></span>



<p>This blog series provides a clear, practical overview of how certificates work, with a focus on signing and distributing macOS applications. Some concepts apply to digital certificates in general, while others are specific to the macOS code signing process. By the end of the series, you’ll understand what certificates are, why they matter, and the role they play when building and distributing a macOS app.</p>



<p>The Developer ID field in the Build Settings &gt; macOS &gt; Sign Inspector Panel is our starting point:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1000" height="574" src="https://blog.xojo.com/wp-content/uploads/2026/02/Captura-de-pantalla-2026-02-26-a-las-10.51.17.png" alt="" class="wp-image-15857" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/Captura-de-pantalla-2026-02-26-a-las-10.51.17.png 1000w, https://blog.xojo.com/wp-content/uploads/2026/02/Captura-de-pantalla-2026-02-26-a-las-10.51.17-300x172.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/Captura-de-pantalla-2026-02-26-a-las-10.51.17-768x441.png 768w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /></figure>



<p>By default, this field is empty. When you click Build, the app bundle (and its contents) is signed using a more relaxed security configuration. This does not require an explicit developer certificate and does not verify that the app comes from a known, trusted developer.</p>



<p>This type of signing is called Ad-Hoc signing. It is perfectly fine when debugging from the IDE or when building apps you intend to run locally.</p>



<p>In earlier versions of macOS, it was even possible to distribute and run Ad-Hoc–signed apps on other Macs, as long as the user explicitly chose to trust them. While this is still technically possible on recent versions of macOS, Apple has continued to tighten security, making it increasingly difficult for users to launch Ad-Hoc–signed applications.</p>



<p>In most cases, <a href="https://support.apple.com/en-au/guide/security/sec5599b66df/web" target="_blank" rel="noreferrer noopener">Gatekeeper</a> will intervene and prevent the app from launching. Since the system cannot verify the identity of a trusted developer, it treats the app as unverified. With Ad-Hoc signing, macOS can only confirm that the app has not been modified since it was signed, it cannot validate who created it.</p>



<h2 class="wp-block-heading">Under the hood: How &#8220;Ad-Hoc&#8221; signing works</h2>



<p>Every time an app is signed (including all the contents inside its bundle) macOS uses Apple’s codesign tool. When Ad-Hoc signing is applied, the simplified process works roughly like this:<br></p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1390" height="812" src="https://blog.xojo.com/wp-content/uploads/2026/02/Ad-Hoc-How-it-works.png" alt="" class="wp-image-15858" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/Ad-Hoc-How-it-works.png 1390w, https://blog.xojo.com/wp-content/uploads/2026/02/Ad-Hoc-How-it-works-300x175.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/Ad-Hoc-How-it-works-1024x598.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/Ad-Hoc-How-it-works-768x449.png 768w" sizes="auto, (max-width: 1390px) 100vw, 1390px" /></figure>



<ul class="wp-block-list">
<li>A hash value (a unique digital fingerprint) is calculated for every file in the app bundle, whether it is executable or not, as well as for the bundle itself.</li>



<li>These hash values are stored inside the app bundle, in the <code>_CodeSignature</code> folder.</li>



<li>If the app contains multiple architectures (for example, x86 and ARM), the process is repeated for each supported architecture.</li>
</ul>



<p>When a user double-clicks the app to launch it, macOS performs a similar verification process:</p>



<ul class="wp-block-list">
<li>It recalculates the hash value for every file in the bundle.</li>



<li>It compares the newly calculated values with those stored in the <code>_CodeSignature</code> folder and if any hash differs from the stored value, macOS determines that the bundle has been modified since it was signed and it will refuse to launch the app.</li>
</ul>



<p>Want to see this in action? Create a new Desktop project in the Xojo IDE, save it to your Documents folder, and build it for macOS.</p>



<p>Next, locate the built app in Finder. Control-click it and choose “Show Package Contents.” Then open the Contents &gt; _CodeSignature folder and inspect the CodeResources file using your favorite text editor. You’ll see a list of hash values and digests corresponding to every file in the app bundle.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1248" height="1344" src="https://blog.xojo.com/wp-content/uploads/2026/02/SignatureFile.png" alt="" class="wp-image-15859" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/SignatureFile.png 1248w, https://blog.xojo.com/wp-content/uploads/2026/02/SignatureFile-279x300.png 279w, https://blog.xojo.com/wp-content/uploads/2026/02/SignatureFile-951x1024.png 951w, https://blog.xojo.com/wp-content/uploads/2026/02/SignatureFile-768x827.png 768w" sizes="auto, (max-width: 1248px) 100vw, 1248px" /></figure>



<h2 class="wp-block-heading">Apple Developer Certificates: Establishing Trust on macOS</h2>



<p>What must you do so your apps are recognized as first-class citizens on macOS and can be distributed without Gatekeeper intervening? The answer is likely familiar: enroll in the Apple Developer Program (currently US $99 per year).</p>



<p>Among its many benefits, membership in the Apple Developer Program allows you to create your own Developer ID certificates. When you use these certificates to sign your apps, macOS can validate the signature and identify you as the verified developer distributing the software.</p>



<p>But how is this trust established and verified? To answer that, we need to start at the very root, literally!</p>



<p>Every computer, smartphone, tablet, and many other devices come with preinstalled Root Certificates. These certificates are issued by trusted organizations known as Root Certificate Authorities (CAs), including Apple. They serve as the foundation of a chain of trust, allowing other certificates issued by those authorities to be verified.</p>



<p>Technically speaking, a Root Certificate Authority (CA) is the top-level trusted entity in a public key infrastructure (<a href="https://en.wikipedia.org/wiki/Public_key_infrastructure">PKI</a>). It issues self-signed root certificates that act as the trust anchor for verifying other digital certificates. In other words, it is the foundation upon which the entire certificate trust model is built.</p>



<p>It is easy to take a look to these installed on your Mac:</p>



<ol class="wp-block-list">
<li>Open Keychain Access.</li>



<li>Select Certificates at the top of the window.</li>



<li>In the sidebar, choose System Roots.</li>



<li>You will then see the complete list of root certificates trusted by macOS.</li>
</ol>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="2186" height="1264" src="https://blog.xojo.com/wp-content/uploads/2026/02/Root-Certificates.png" alt="" class="wp-image-15860" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/Root-Certificates.png 2186w, https://blog.xojo.com/wp-content/uploads/2026/02/Root-Certificates-300x173.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/Root-Certificates-1024x592.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/Root-Certificates-768x444.png 768w, https://blog.xojo.com/wp-content/uploads/2026/02/Root-Certificates-1536x888.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/02/Root-Certificates-2048x1184.png 2048w" sizes="auto, (max-width: 2186px) 100vw, 2186px" /></figure>



<p>You’ll notice that there are three different Apple Root CA certificates. Why?</p>



<p>Each <a href="https://en.wikipedia.org/wiki/X.509" target="_blank" rel="noreferrer noopener">X.509</a> certificate contains detailed metadata defining its cryptographic properties and permitted usage. This includes the key type (such as <a href="https://en.wikipedia.org/wiki/RSA_cryptosystem" target="_blank" rel="noreferrer noopener">RSA</a> or <a href="https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm" target="_blank" rel="noreferrer noopener">ECDSA</a>), the public key length, and the signature algorithm used.</p>



<ul class="wp-block-list">
<li><strong>Apple Root CA</strong>: Is a RSA type, with a public key length of 2048 bits that uses the SHA-1 algorithm.</li>



<li><strong>Apple Root CA-G2</strong>: Is a RSA type, with a public key length of 4096 bits that uses the SHA-384 algorithm.</li>



<li><strong>Apple Root CA-G3</strong>: Is a ECDSA type, with a public key length of 384 bits that uses the SHA-384 algorithm.</li>
</ul>



<h2 class="wp-block-heading">Intermediate Certificates and the Chain of Trust</h2>



<p>Root certificates are highly valuable and sensitive, so they are rarely used directly to sign end-user certificates (also called “Leaf” certificates). In the case of macOS app development, the developer’s certificate is the Leaf. This is where Intermediate Certificates come into play.</p>



<p>In simple terms, Intermediate Certificates are signed by Root Certificates and, in turn, are used to sign Leaf certificates. This protects the Root certificate from direct exposure. Together, the Root, Intermediate, and Leaf certificates form what is called the “Chain of Trust.”</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1254" height="932" src="https://blog.xojo.com/wp-content/uploads/2026/02/Root-Intermediate-Lead-Span.png" alt="" class="wp-image-15861" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/Root-Intermediate-Lead-Span.png 1254w, https://blog.xojo.com/wp-content/uploads/2026/02/Root-Intermediate-Lead-Span-300x223.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/Root-Intermediate-Lead-Span-1024x761.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/Root-Intermediate-Lead-Span-768x571.png 768w" sizes="auto, (max-width: 1254px) 100vw, 1254px" /></figure>



<p>The Chain of Trust verification starts with the Leaf certificate and works upward through the Intermediate to the Root. This same process occurs whenever you visit a secure website, make an online payment, or transmit sensitive data securely.</p>



<p>For example, the Leaf certificate is validated against its Intermediate certificate. If the Intermediate certificate is missing or expired, the Leaf certificate is considered invalid. Similarly, the Intermediate certificate itself must be validated against the Root certificate. If the Root certificate is missing or expired, the Intermediate is invalid, and all Leaf certificates signed by it are also invalid.</p>



<p>The same process happens when you sign your macOS apps: macOS validates the entire certificate chain before allowing the app to run.</p>



<p>Finally, certificates closer to the Root generally have longer validity periods. Leaf certificates must be renewed more frequently, while Root certificates are valid for many years.</p>



<h2 class="wp-block-heading">Wrapping up</h2>



<p>In this first article, we covered the fundamentals of digital certificates and their role in macOS app security. In the next article, we will focus specifically on Apple Developer certificates and how they enable trusted app distribution.</p>



<p><em>Javier Menendez is an engineer at Xojo and has been using Xojo since 1998. He lives in Castellón</em>, <em>Spain and hosts regular Xojo hangouts en español. Ask Javier questions on Twitter at <a href="https://twitter.com/xojoes" target="_blank" rel="noreferrer noopener">@XojoES</a> or on the <a href="https://forum.xojo.com/u/javier_menendez/summary" target="_blank" rel="noreferrer noopener">Xojo Forum</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p><strong>Code Signing on macOS: What Developers Need to Know</strong></p>



<ul class="wp-block-list">
<li><a href="https://blog.xojo.com/2026/03/04/code-signing-on-macos-what-developers-need-to-know-part-1/" target="_blank" rel="noreferrer noopener">Part 1, Get Started</a></li>



<li><a href="https://blog.xojo.com/2026/03/18/code-signing-on-macos-what-developers-need-to-know-part-2/" target="_blank" rel="noreferrer noopener">Part 2, Code Signing With Developer Certificates</a></li>



<li><a href="https://blog.xojo.com/2026/03/24/code-signing-on-macos-what-developers-need-to-know-part-3/">Part 3, Entitlements and Provisioning Profiles</a></li>



<li><a href="https://blog.xojo.com/2026/04/07/code-signing-on-macos-what-developers-need-to-know-part-4/" target="_blank" rel="noreferrer noopener">Part 4, How Xojo helps with Certificates, Signing and Distribution</a></li>
</ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Scatter Chart: Connecting the Points</title>
		<link>https://blog.xojo.com/2026/02/09/scatter-chart-connecting-the-points/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Mon, 09 Feb 2026 16:26:56 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Charts]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15826</guid>

					<description><![CDATA[A user recently asked whether it’s possible to connect the (x, y) points in a Scatter chart using DesktopChart, and if so, how to do&#8230;]]></description>
										<content:encoded><![CDATA[
<p>A user recently asked whether it’s possible to connect the (x, y) points in a Scatter chart using DesktopChart, and if so, how to do it. The short answer is yes, it is possible. Read on and I’ll show you just how easy it is.</p>



<span id="more-15826"></span>



<p>For this example, we’ll use the x and y coordinate values of the sine and cosine functions as the data for our scatter DataSets. Go ahead and create a new Desktop project in the Xojo IDE.</p>



<p>Next, select the default Window1 and drag a DesktopChart control from the Library panel into the Layout Editor for Window1. Adjust the right margin to the recommended right layout guide, then lock the Top, Left, and Right layout locks for the Chart1 instance using the Inspector. At this point, your design should look similar to this:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="2560" height="1800" src="https://blog.xojo.com/wp-content/uploads/2026/02/Chart1-scaled.png" alt="" class="wp-image-15827" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/Chart1-scaled.png 2560w, https://blog.xojo.com/wp-content/uploads/2026/02/Chart1-300x211.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/Chart1-1024x720.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/Chart1-768x540.png 768w, https://blog.xojo.com/wp-content/uploads/2026/02/Chart1-1536x1080.png 1536w, https://blog.xojo.com/wp-content/uploads/2026/02/Chart1-2048x1440.png 2048w" sizes="auto, (max-width: 2560px) 100vw, 2560px" /></figure>



<p>While you’re there, select Chart1 and, in the Inspector, set the option Behavior &gt; Mode to Scatter.</p>



<p>Next, with Window1 selected, add two properties using the following values:</p>



<p><strong>Property 1:</strong></p>



<ul class="wp-block-list">
<li><strong>Name:</strong> CosStyle</li>



<li><strong>Type:</strong> ChartLinearStyle</li>



<li><strong>Scope:</strong> Private</li>
</ul>



<p><strong>Property 2</strong></p>



<ul class="wp-block-list">
<li><strong>Name:</strong> SineStyle</li>



<li><strong>Type:</strong> ChartLinearStyle</li>



<li><strong>Scope:</strong> Private</li>
</ul>



<p>These properties will be used to store references to the Style objects associated with the cosine and sine function DataSets.</p>



<p>Finally, with Window1 still selected, add the Opening event and enter the following lines of code into the associated code editor:</p>



<pre class="wp-block-preformatted">CosStyle = New ChartLinearStyle<br>CosStyle.Line = ChartLinearStyle.LineTypes.Dashed<br><br>SineStyle = New ChartLinearStyle<br>SineStyle.Line = ChartLinearStyle.LineTypes.Solid<br><br>DrawScatterChart</pre>



<p>In brief, this code creates new ChartLinearStyle instances for the properties added earlier. It assigns a solid line style to connect the cosine function data points and a dashed line style to connect the sine function data points. After that, it calls the DrawScatterChart method, which is responsible for rendering the sine and cosine functions on the Chart1 instance.</p>



<p>Now, let’s create that method on Window1 using the following values in the Inspector:</p>



<ul class="wp-block-list">
<li><strong>Name:</strong> DrawScatterChart</li>



<li><strong>Scope:</strong> Private</li>
</ul>



<p>Type the following snippet of code in the associated Code Editor for the method:</p>



<pre class="wp-block-code"><code>// These are the Array variables in charge of storing the Scatter data points
// for the Sine and Cosine functions
Var sinePoints() As ChartScatterDatapoint
Var cosinePoints() As ChartScatterDatapoint

// …and these variables will handle the DataSet instances
// for the previous arrays of data points on both functions
Var sineDataSet As ChartScatterDataset
var cosDataSet As ChartScatterDataset

Const pi = 3.14159265359
Var y As Double
Var maxXValue As Double = 2.0 * pi

// Using a simple loop to feed the x and y
// values for the Sine and Cosine
For x As Double = 0.0 To maxXValue Step 0.5
  
  y = Sin(x)
  sinePoints.Add(New ChartScatterDatapoint(x, y, 1))
  
  y = Cos(x)
  cosinePoints.Add(new ChartScatterDatapoint(x, y, 1))
  
Next

// Next, we create the new instances for the Scatter DataSets
sineDataSet = New ChartScatterDataset(Color.Blue, sinePoints)
cosDataSet = New ChartScatterDataset(color.Red, cosinePoints)

// …and we set the Style to be used on each of them
sineDataSet.Style = SineStyle
cosDataSet.Style = CosStyle

// … and of course the labels to be shown on the Legend section
// of the chart itself
sineDataSet.Label = "Sine Function"
cosDataSet.Label = "Cos Function"

// As the last step, we add both DataSets to the chart
// so these can be rendered
Chart1.AddDatasets(sineDataSet, cosDataSet)</code></pre>



<p>Run the app, and it should look similar to this:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1424" height="1088" src="https://blog.xojo.com/wp-content/uploads/2026/02/Chart2.png" alt="" class="wp-image-15828" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/Chart2.png 1424w, https://blog.xojo.com/wp-content/uploads/2026/02/Chart2-300x229.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/Chart2-1024x782.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/Chart2-768x587.png 768w" sizes="auto, (max-width: 1424px) 100vw, 1424px" /></figure>



<h2 class="wp-block-heading">A change of Style… on the fly!</h2>



<p>As with many aspects of DesktopChart, any changes made at runtime are reflected immediately, without the need to redraw the chart, re-feed the data sets, or perform any other complex operations. Let’s take advantage of this by changing the sine and cosine styles at runtime, allowing users of our example app to toggle whether the points are connected.</p>



<p>Add two DesktopCheckBox controls below the bottom margin of the Chart1 instance on Window1. Set the Caption of the first checkbox to “Connect Sine Points” and the second to “Connect Cos Points.” For both checkboxes, use the Inspector to set Initial State &gt; Visual State to Checked.</p>



<p>The final layout should look similar to this:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1292" height="954" src="https://blog.xojo.com/wp-content/uploads/2026/02/Chart3.png" alt="" class="wp-image-15829" srcset="https://blog.xojo.com/wp-content/uploads/2026/02/Chart3.png 1292w, https://blog.xojo.com/wp-content/uploads/2026/02/Chart3-300x222.png 300w, https://blog.xojo.com/wp-content/uploads/2026/02/Chart3-1024x756.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/02/Chart3-768x567.png 768w" sizes="auto, (max-width: 1292px) 100vw, 1292px" /></figure>



<p>Lastly, add the ValueChanged event to both CheckBox instances. Then, for the checkbox with the caption “Connect Sine Points,” add the following lines of code to its event handler:</p>



<pre class="wp-block-code"><code>If Me.Value Then
  SineStyle.Line = ChartLinearStyle.LineTypes.Dashed
Else
  SineStyle.Line = ChartLinearStyle.LineTypes.None
End If</code></pre>



<p>Add the following lines of code to the ValueChanged event handler for the checkbox with the caption “Connect Cos Points”:</p>



<pre class="wp-block-code"><code>If Me.Value Then
  CosStyle.Line = ChartLinearStyle.LineTypes.Solid
Else
  CosStyle.Line = ChartLinearStyle.LineTypes.None
End If</code></pre>



<p>Run the app again and, this time, click each checkbox to see how the points are no longer connected when a checkbox is unchecked, and are connected when it is selected.</p>



<figure class="wp-block-video"><video controls src="https://blog.xojo.com/wp-content/uploads/2026/02/Grabacion-de-pantalla-2026-02-02-a-las-13.53.35.mp4"></video></figure>



<h2 class="wp-block-heading">Summary</h2>



<p>As you can see, styles can be used not only to connect points in a Scatter chart, but also to customize the point endpoints beyond the default appearance. For example, you can set the endpoint to “None” or choose from many other available options. Even better, any changes made to a style at runtime are applied immediately.</p>



<p><em>Javier Menendez is an engineer at Xojo and has been using Xojo since 1998. He lives in Castellón</em>, <em>Spain and hosts regular Xojo hangouts en español. Ask Javier questions on Twitter at <a href="https://twitter.com/xojoes" target="_blank" rel="noreferrer noopener">@XojoES</a> or on the <a href="https://forum.xojo.com/u/javier_menendez/summary" target="_blank" rel="noreferrer noopener">Xojo Forum</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2026/02/Grabacion-de-pantalla-2026-02-02-a-las-13.53.35.mp4" length="171622" type="video/mp4" />

			</item>
		<item>
		<title>Xojo + XAML + Goto = &#x1f525;</title>
		<link>https://blog.xojo.com/2026/01/22/xojo-xaml-goto/</link>
		
		<dc:creator><![CDATA[William Yu]]></dc:creator>
		<pubDate>Thu, 22 Jan 2026 20:50:59 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Fun]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[Animation]]></category>
		<category><![CDATA[DesktopXAMLContainer]]></category>
		<category><![CDATA[XAML]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15790</guid>

					<description><![CDATA[For decades, Goto has been treated as a programming faux pas—something to avoid at all costs. Like most rules though, there are exceptions. The Goto&#8230;]]></description>
										<content:encoded><![CDATA[
<p>For decades, Goto has been treated as a programming faux pas—something to avoid at all costs. Like most rules though, there are exceptions. The Goto I’m talking about here is one of them… and it can quite literally light your app on fire—programmatically speaking.</p>



<p>One of the hidden gems in <a href="https://xojo.com/download/" target="_blank" rel="noreferrer noopener">Xojo 2025r3</a> is support for XAML transitions, which makes it possible to add lightweight animations to your UI without writing any custom animation code in Xojo. Instead, you define visual states in XAML and let the XAML engine handle the animation for you.</p>



<p>At a high level, the workflow looks like this:</p>



<ol class="wp-block-list">
<li>Define one or more&nbsp;<strong>VisualStates</strong>&nbsp;in XAML.</li>



<li>Attach transitions to those states (for example, moving or fading an element).</li>



<li>From Xojo code, switch between states using&nbsp;<code>Invoke("GotoState", ...)</code>.</li>
</ol>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" />&nbsp;<strong>Pro Tip</strong><br><code>DesktopXAMLContainer</code>&nbsp;subscribes to&nbsp;<code>Operator_Lookup</code>, so you don’t have to call&nbsp;<code>Invoke</code>&nbsp;directly. Instead of writing<code> XAMLContainer1.Invoke("GotoState", "WhichState")</code>, you can simply call <code>XAMLContainer1.GotoState("WhichState")</code>.</p>



<h3 class="wp-block-heading">Visual States in XAML</h3>



<p>A&nbsp;<em>VisualState</em>&nbsp;represents a named configuration of UI properties. When you transition from one state to another, XAML can automatically animate the change.</p>



<p>Below is a simple example that animates a fire emoji <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f525.png" alt="🔥" class="wp-smiley" style="height: 1em; max-height: 1em;" /> moving upward, similar to a candle flame flickering or burning upward.</p>



<h3 class="wp-block-heading">Example XAML</h3>



<p>This example uses a&nbsp;<code>TextBlock</code>&nbsp;to display the fire emoji and animates its vertical position with a&nbsp;<code>TranslateTransform</code>. Note that visual states must be defined on a control, so we attach them to a&nbsp;<code>UserControl</code>, allowing it to participate in&nbsp;<code>GotoState</code>&nbsp;transitions.</p>



<pre class="wp-block-preformatted">&lt;UserControl&gt;<br>  &lt;Grid&gt;<br>    &lt;VisualStateManager.VisualStateGroups&gt;<br>      &lt;VisualStateGroup Name="FlameStates"&gt;<br><br>        &lt;VisualState Name="Bottom"&gt;<br>          &lt;Storyboard&gt;<br>            &lt;DoubleAnimation<br>              Storyboard.TargetName="FlameTransform"<br>              Storyboard.TargetProperty="Y"<br>              To="40"<br>              Duration="0:0:1" /&gt;<br>          &lt;/Storyboard&gt;<br>        &lt;/VisualState&gt;<br><br>        &lt;VisualState Name="Top"&gt;<br>          &lt;Storyboard&gt;<br>            &lt;DoubleAnimation<br>              Storyboard.TargetName="FlameTransform"<br>              Storyboard.TargetProperty="Y"<br>              To="-100"<br>              Duration="0:0:1" /&gt;<br>          &lt;/Storyboard&gt;<br>        &lt;/VisualState&gt;<br><br>      &lt;/VisualStateGroup&gt;<br>    &lt;/VisualStateManager.VisualStateGroups&gt;<br><br>    &lt;TextBlock<br>      Text="<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f525.png" alt="🔥" class="wp-smiley" style="height: 1em; max-height: 1em;" />"<br>      FontSize="32"<br>      HorizontalAlignment="Center"<br>      VerticalAlignment="Bottom"&gt;<br><br>      &lt;TextBlock.RenderTransform&gt;<br>        &lt;TranslateTransform Name="FlameTransform" /&gt;<br>      &lt;/TextBlock.RenderTransform&gt;<br><br>    &lt;/TextBlock&gt;<br>  &lt;/Grid&gt;<br>&lt;/UserControl&gt;</pre>



<p>In this XAML:</p>



<ul class="wp-block-list">
<li>The&nbsp;<code>VisualStateGroup</code>&nbsp;named&nbsp;<strong>FlameStates</strong>&nbsp;contains two states:
<ul class="wp-block-list">
<li><strong>Bottom</strong>&nbsp;– moves the emoji downward.</li>



<li><strong>Top</strong>&nbsp;– moves the emoji upward.</li>
</ul>
</li>



<li>The&nbsp;<code>DoubleAnimation</code>&nbsp;targets the&nbsp;<code>Y</code>&nbsp;property of a&nbsp;<code>TranslateTransform</code>.</li>



<li>The transition duration is handled entirely by XAML.</li>
</ul>



<h3 class="wp-block-heading">Triggering the Transition from Xojo</h3>



<p>Once the visual states are defined, switching between them from Xojo is straightforward. Assuming this XAML is hosted in a&nbsp;<code>XAMLContainer</code>&nbsp;named&nbsp;<code>XAMLContainer1</code>, you can trigger the animation like this:</p>



<pre class="wp-block-code"><code>XAMLContainer1.GotoState("Top")</code></pre>



<p>And to move it back down:</p>



<pre class="wp-block-code"><code>XAMLContainer1.GotoState("Bottom")</code></pre>



<h3 class="wp-block-heading">Why This Is Powerful</h3>



<p>What makes this feature especially useful is that:</p>



<ul class="wp-block-list">
<li>The animation logic stays in XAML, where it naturally belongs.</li>



<li>Xojo code remains clean and declarative—just tell the UI&nbsp;<em>which state</em>&nbsp;to go to.</li>



<li>More complex effects (opacity, scaling, rotation, easing functions) can be added without changing any Xojo code.</li>
</ul>



<p>Here&#8217;s a more interesting variation, where the flames drift upward rather than moving in a straight line:</p>



<pre class="wp-block-code"><code>&lt;UserControl&gt;
  &lt;Grid Width="160" Height="240"&gt;

    &lt;!-- Fire emoji 1 --&gt;
    &lt;TextBlock Name="Fire1"
           Text="&#x1f525;"
           FontSize="32"
           VerticalAlignment="Bottom"
           HorizontalAlignment="Center"&gt;
      &lt;TextBlock.RenderTransform&gt;
        &lt;TranslateTransform Name="Move1"/&gt;
      &lt;/TextBlock.RenderTransform&gt;
    &lt;/TextBlock&gt;

    &lt;!-- Fire emoji 2 --&gt;
    &lt;TextBlock Name="Fire2"
           Text="&#x1f525;"
           FontSize="26"
           VerticalAlignment="Bottom"
           HorizontalAlignment="Center"
           Margin="20,0,0,0"
           Opacity="0.8"&gt;
      &lt;TextBlock.RenderTransform&gt;
        &lt;TranslateTransform Name="Move2"/&gt;
      &lt;/TextBlock.RenderTransform&gt;
    &lt;/TextBlock&gt;

    &lt;!-- Fire emoji 3 --&gt;
    &lt;TextBlock Name="Fire3"
           Text="&#x1f525;"
           FontSize="22"
           VerticalAlignment="Bottom"
           HorizontalAlignment="Center"
           Margin="-20,0,0,0"
           Opacity="0.7"&gt;
      &lt;TextBlock.RenderTransform&gt;
        &lt;TranslateTransform Name="Move3"/&gt;
      &lt;/TextBlock.RenderTransform&gt;
    &lt;/TextBlock&gt;

    &lt;VisualStateManager.VisualStateGroups&gt;
      &lt;VisualStateGroup Name="FireStates"&gt;

        &lt;VisualState Name="Off"/&gt;

        &lt;VisualState Name="On"&gt;
          &lt;Storyboard RepeatBehavior="Forever"&gt;

            &lt;!-- Fire 1 --&gt;
            &lt;DoubleAnimation Storyboard.TargetName="Move1"
                     Storyboard.TargetProperty="Y"
                     From="0"
                     To="-180"
                     Duration="0:0:1.2"/&gt;

            &lt;DoubleAnimation Storyboard.TargetName="Move1"
                     Storyboard.TargetProperty="X"
                     From="0"
                     To="10"
                     Duration="0:0:0.6"
                     AutoReverse="True"/&gt;

            &lt;!-- Fire 2 --&gt;
            &lt;DoubleAnimation Storyboard.TargetName="Move2"
                     Storyboard.TargetProperty="Y"
                     From="0"
                     To="-160"
                     Duration="0:0:1.0"
                     BeginTime="0:0:0.3"/&gt;

            &lt;DoubleAnimation Storyboard.TargetName="Move2"
                     Storyboard.TargetProperty="X"
                     From="0"
                     To="-12"
                     Duration="0:0:0.5"
                     AutoReverse="True"/&gt;

            &lt;!-- Fire 3 --&gt;
            &lt;DoubleAnimation Storyboard.TargetName="Move3"
                     Storyboard.TargetProperty="Y"
                     From="0"
                     To="-140"
                     Duration="0:0:1.4"
                     BeginTime="0:0:0.15"/&gt;

            &lt;DoubleAnimation Storyboard.TargetName="Move3"
                     Storyboard.TargetProperty="X"
                     From="0"
                     To="8"
                     Duration="0:0:0.7"
                     AutoReverse="True"/&gt;

          &lt;/Storyboard&gt;
        &lt;/VisualState&gt;

      &lt;/VisualStateGroup&gt;
    &lt;/VisualStateManager.VisualStateGroups&gt;

  &lt;/Grid&gt;
&lt;/UserControl&gt;</code></pre>



<p>To light up the flames we&#8217;ll simply invoke the &#8220;On&#8221; state:</p>



<pre class="wp-block-code"><code>XAMLContainer1.GotoState("On")</code></pre>



<figure class="wp-block-video"><video height="720" style="aspect-ratio: 1280 / 720;" width="1280" controls loop src="https://blog.xojo.com/wp-content/uploads/2026/01/XAMLFire.mp4" playsinline></video></figure>



<p>For subtle UI polish—like animated indicators, highlights, or playful effects such as this candle flame—XAML transitions provide a surprisingly powerful new tool in Xojo.</p>



<p><em><em><em>William Yu grew up in Canada learning to program BASIC on a Vic-20. He is Xojo’s resident Windows and Linux engineer, among his many other skills. Some may say he has joined the dark side here in the USA, but he will always be a Canadian at heart.</em></em></em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2026/01/XAMLFire.mp4" length="177770" type="video/mp4" />

			</item>
		<item>
		<title>Detecting UI Compatibility Mode in macOS Apps with Xojo</title>
		<link>https://blog.xojo.com/2026/01/14/detecting-ui-compatibility-mode-in-macos-apps-with-xojo/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Wed, 14 Jan 2026 22:49:34 +0000</pubDate>
				<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Declares]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15762</guid>

					<description><![CDATA[As you may already know, starting with Xojo 2025r3, macOS apps can be developed and compiled with UI Compatibility Mode either enabled or disabled. Now&#8230;]]></description>
										<content:encoded><![CDATA[
<p>As you may already know, starting with Xojo 2025r3, macOS apps can be developed and compiled with UI Compatibility Mode either enabled or disabled. Now imagine you are creating a Library intended for use in other projects and, as part of its UI-related functionality, the Library needs to determine whether the host application is running with UI Compatibility Mode enabled. How can you do that? Read on to find out.</p>



<span id="more-15762"></span>



<p>To determine whether a macOS app is running with UI Compatibility Mode enabled, we’ll use a small set of <a href="https://documentation.xojo.com/topics/declares/calling_native_macos_apis.html">Declares</a> inside a method contained in a Module, purely for the purposes of this example. Begin by creating a new Desktop project and adding a new Module to it (for example, a simple “Module1”). Next, add a new method to the Module with the following signature:</p>



<p><code>IsCompatibilityModeEnabled As Boolean</code></p>



<p>Then add the following code to the method:</p>



<pre class="wp-block-code"><code>#If TargetMacOS Then
  
  If System.Version.MajorVersion >= 26 Then
    
    Declare Function NSClassFromString Lib "Foundation" (clsName As CFStringRef) As Ptr
    Declare Function NSMainBundle Lib "AppKit" Selector "mainBundle" (obj As Ptr) As Ptr
    Declare Function NSInfoDictionary Lib "AppKit" Selector "infoDictionary" (obj As Ptr) As Ptr
    Declare Function NSDictValueForKey Lib "AppKit" Selector "valueForKey:" (obj As Ptr, key As CFStringRef) As Ptr
    Declare Function NSGetBoolValue Lib "AppKit" Selector "boolValue" (obj As Ptr) As Boolean
    
    Var Bundle As Ptr = NSClassFromString("NSBundle")
    
    If Bundle &lt;> Nil Then
      Var MainBundle As Ptr = NSMainBundle(Bundle)
      
      If MainBundle &lt;> Nil then
        Var infoDictionaryPlist As Ptr = NSInfoDictionary(MainBundle)
        
        If infoDictionaryPlist &lt;> Nil Then
          Var valueObj As Ptr = NSDictValueForKey(infoDictionaryPlist, "UIDesignRequiresCompatibility")
          
          If valueObj &lt;> Nil Then 
            Return NSGetBoolValue(valueObj)
          End If
          
        End If
        
      End If
      
    End If
  End If
  
  Return False
  
#EndIf</code></pre>



<p>In short, the previous code retrieves the app’s Info.plist from the macOS bundle and loads it into an NSDictionary object (similar to Xojo’s Dictionary). It then attempts to access the value associated with the key <code>UIDesignRequiresCompatibility</code>. If the returned object is Nil, it means the Info.plist does not contain that key and the app is therefore running in native macOS Tahoe mode. If the key is present, the method returns the Boolean value associated with it; a value of True indicates that the app is running with UI Compatibility Mode enabled under macOS Tahoe. That’s all there is to it!</p>



<h2 class="wp-block-heading">Testing the Method</h2>



<p>Now add a DesktopButton to the project’s default window and implement its Pressed event. Next, insert the following line of code into the associated Code Editor:</p>



<pre class="wp-block-code"><code>MessageBox("Compatibility Mode Enabled: " +  IsCompatibilityModeEnabled.ToString)</code></pre>



<p>For testing purposes, select Build Settings &gt; macOS in the Project Browser and enable UI Compatibility Mode, which can be found under the Build section of the Inspector. Run the app and, if your Mac is running macOS 26 or later, you will see the following message:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1204" height="860" src="https://blog.xojo.com/wp-content/uploads/2026/01/Captura-de-pantalla-2026-01-08-a-las-14.26.54.png" alt="" class="wp-image-15763" srcset="https://blog.xojo.com/wp-content/uploads/2026/01/Captura-de-pantalla-2026-01-08-a-las-14.26.54.png 1204w, https://blog.xojo.com/wp-content/uploads/2026/01/Captura-de-pantalla-2026-01-08-a-las-14.26.54-300x214.png 300w, https://blog.xojo.com/wp-content/uploads/2026/01/Captura-de-pantalla-2026-01-08-a-las-14.26.54-1024x731.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/01/Captura-de-pantalla-2026-01-08-a-las-14.26.54-768x549.png 768w" sizes="auto, (max-width: 1204px) 100vw, 1204px" /></figure>



<p>Quit the app and return to Build Settings &gt; macOS to disable UI Compatibility Mode. Run the app again and this time you will see the following message:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1204" height="866" src="https://blog.xojo.com/wp-content/uploads/2026/01/Captura-de-pantalla-2026-01-08-a-las-14.28.22.png" alt="" class="wp-image-15764" srcset="https://blog.xojo.com/wp-content/uploads/2026/01/Captura-de-pantalla-2026-01-08-a-las-14.28.22.png 1204w, https://blog.xojo.com/wp-content/uploads/2026/01/Captura-de-pantalla-2026-01-08-a-las-14.28.22-300x216.png 300w, https://blog.xojo.com/wp-content/uploads/2026/01/Captura-de-pantalla-2026-01-08-a-las-14.28.22-1024x737.png 1024w, https://blog.xojo.com/wp-content/uploads/2026/01/Captura-de-pantalla-2026-01-08-a-las-14.28.22-768x552.png 768w" sizes="auto, (max-width: 1204px) 100vw, 1204px" /></figure>



<h2 class="wp-block-heading">In Summary</h2>



<p>As you can see, Declares are a powerful feature in Xojo’s extensive toolbox, allowing developers to directly access and use APIs provided by the operating system. In this case, they enable you to retrieve the app’s Info.plist from the main bundle, load it into a dictionary, and read the value associated with a specific key.</p>



<p><em>Javier Menendez is an engineer at Xojo and has been using Xojo since 1998. He lives in Castellón</em>, <em>Spain and hosts regular Xojo hangouts en español. Ask Javier questions on Twitter at <a href="https://twitter.com/xojoes" target="_blank" rel="noreferrer noopener">@XojoES</a> or on the <a href="https://forum.xojo.com/u/javier_menendez/summary" target="_blank" rel="noreferrer noopener">Xojo Forum</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Tip: Customize Toolbars on macOS apps</title>
		<link>https://blog.xojo.com/2025/12/17/tip-customize-toolbars-on-macos-apps/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Wed, 17 Dec 2025 17:04:00 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[2025r3]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[macOS 26]]></category>
		<category><![CDATA[Toolbar]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15727</guid>

					<description><![CDATA[Starting with Xojo 2025r3, macOS apps are built using macOS SDK 26. One benefit of this is that your apps automatically gain access to newer&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Starting with Xojo 2025r3, macOS apps are built using macOS SDK 26. One benefit of this is that your apps automatically gain access to newer native macOS features with little or no extra work. In some cases, these features are available immediately; in others, they can be enabled with a simple Declare. One such example is allowing users to customize an app’s toolbar.</p>



<p>To demonstrate this, we’ll use the Desktop Toolbar example project that ships with Xojo. You can find it in the Examples section of the New Project window. Open this project using the Xojo 2025r3 IDE.</p>



<p>Once the project is open, locate the MainWindow in the Project Browser. Under MainWindow, select the WindowToolbar item and then choose its Opening event. At the top of the Code Editor for this event, add the following lines of code:</p>



<pre class="wp-block-code"><code>Var hdl As Ptr = Me.Handle
If hdl.Integer &lt;> 0 Then
  Declare Sub AllowCustomization Lib "AppKit" Selector "setAllowsUserCustomization:" (hdl As Ptr, value As Boolean)
  AllowCustomization(hdl, True)
End If</code></pre>



<p>It&#8217;s that simple!</p>



<figure class="wp-block-video"><video controls src="https://blog.xojo.com/wp-content/uploads/2025/12/Grabacion-de-pantalla-2025-12-09-a-las-14.13.05.mp4"></video></figure>



<p>Run the app and open the contextual menu by right-clicking (or Control-clicking) on the window’s toolbar. You’ll see a new Customize Toolbar menu item. Select it to open the standard macOS toolbar customization panel, where you can rearrange or remove items as you like. When you click OK, your changes are immediately applied to the current toolbar.</p>



<p>One important caveat: these customizations are not preserved between app launches. This happens because each toolbar must have a unique identifier that macOS uses to save and restore its configuration. Since the example toolbar does not provide one, the OS has nothing to store or retrieve. But… who knows what the future holds?</p>



<p><em>Javier Menendez is an engineer at Xojo and has been using Xojo since 1998. He lives in Castellón</em>, <em>Spain and hosts regular Xojo hangouts en español. Ask Javier questions on Twitter at <a href="https://twitter.com/xojoes" target="_blank" rel="noreferrer noopener">@XojoES</a> or on the <a href="https://forum.xojo.com/u/javier_menendez/summary" target="_blank" rel="noreferrer noopener">Xojo Forum</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2025/12/Grabacion-de-pantalla-2025-12-09-a-las-14.13.05.mp4" length="512280" type="video/mp4" />

			</item>
		<item>
		<title>macOS and iOS: UI Compatibility Mode</title>
		<link>https://blog.xojo.com/2025/12/09/macos-and-ios-ui-compatibility-mode/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Tue, 09 Dec 2025 16:31:52 +0000</pubDate>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[2025r3]]></category>
		<category><![CDATA[Liquid Glass]]></category>
		<category><![CDATA[macOS 26]]></category>
		<category><![CDATA[macOS Tahoe]]></category>
		<category><![CDATA[UI]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15600</guid>

					<description><![CDATA[macOS 26 and iOS 26 bring many changes, most notably a major UI overhaul. This means that some elements in your existing layouts, both small&#8230;]]></description>
										<content:encoded><![CDATA[
<p>macOS 26 and iOS 26 bring many changes, most notably a major UI overhaul. This means that some elements in your existing layouts, both small and significant, may look different. To help developers with this transition, Apple has introduced UI Compatibility Mode in both operating systems for this release.</p>



<p>So, what is UI Compatibility Mode? It’s Apple’s way of ensuring that your app’s UI appears in macOS 26 and iOS 26 just as it did on previous OS versions. No Liquid Glass effects, no unexpected changes in control sizes or behavior, everything stays as you designed it. This means your pixel-perfect layouts from older OS versions, like Sequoia or iOS 18, will continue to look exactly as intended.</p>



<p>More technically, when UI Compatibility Mode is enabled, your app behaves as if it were compiled with an earlier SDK.</p>



<p>The caveat: Apple only guarantees this behavior while macOS 26 and iOS 26 are current. With the next major OS releases, this mode may no longer be available, so it’s a temporary solution.</p>



<p>The upside: At the time of writing, Apple is still refining these OS versions with point releases. If you need your app to run on macOS 26 or iOS 26 with full compatibility, you can enable UI Compatibility Mode in the Inspector Panel under Build Settings &gt; macOS and Build Settings &gt; iOS.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="441" src="https://blog.xojo.com/wp-content/uploads/2025/12/CompatibilityModeSwitch-1024x441.png" alt="" class="wp-image-15606" srcset="https://blog.xojo.com/wp-content/uploads/2025/12/CompatibilityModeSwitch-1024x441.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/12/CompatibilityModeSwitch-300x129.png 300w, https://blog.xojo.com/wp-content/uploads/2025/12/CompatibilityModeSwitch-768x331.png 768w, https://blog.xojo.com/wp-content/uploads/2025/12/CompatibilityModeSwitch.png 1234w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>When enabled, both your debugged apps and the built versions (including those submitted to Apple via Publish) will look and behave on macOS 26 and iOS 26 as if they were compiled with the previous SDK. In fact, the behavior is even more consistent than if they had been compiled using the prior Xojo release.</p>



<p>Below, you can see how the same app appears when running on macOS 26 and iOS 26 with UI Compatibility Mode turned off (showing Liquid Glass and all the new UI effects), compared to how it looks when the switch is turned on:</p>



<figure class="wp-block-image size-full"><img decoding="async" src="https://blog.xojo.com/wp-content/uploads/2025/12/UICompatibilityModeMacOS.png" alt="" class="wp-image-15601"/></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="970" height="1024" src="https://blog.xojo.com/wp-content/uploads/2025/12/UICompatibilityModeiOS-970x1024.png" alt="" class="wp-image-15603" srcset="https://blog.xojo.com/wp-content/uploads/2025/12/UICompatibilityModeiOS-970x1024.png 970w, https://blog.xojo.com/wp-content/uploads/2025/12/UICompatibilityModeiOS-284x300.png 284w, https://blog.xojo.com/wp-content/uploads/2025/12/UICompatibilityModeiOS-768x811.png 768w, https://blog.xojo.com/wp-content/uploads/2025/12/UICompatibilityModeiOS.png 1697w" sizes="auto, (max-width: 970px) 100vw, 970px" /></figure>



<h2 class="wp-block-heading">The Last Word</h2>



<p>All in all, macOS 26 and iOS 26 introduce a major UI overhaul, which can change the appearance of existing layouts. To help developers, Apple has added UI Compatibility Mode, which lets your apps appear on these new OS versions just as they did on previous releases—no Liquid Glass effects or layout changes. Technically, enabling this mode makes your app behave as if it were compiled with an earlier SDK. While Apple only guarantees this behavior for macOS 26 and iOS 26, it ensures consistency for both debugged and built apps, including those submitted via Publish.</p>



<p>UI Compatibility Mode gives you a choice: enable it to preserve your exact layouts across all OS versions, or leave it off to adopt the new macOS 26 and iOS 26 look and feel, which may require adjusting your UI for some quirks.</p>



<p><em>Javier Menendez is an engineer at Xojo and has been using Xojo since 1998. He lives in Castellón</em>, <em>Spain and hosts regular Xojo hangouts en español. Ask Javier questions on Twitter at <a href="https://twitter.com/xojoes" target="_blank" rel="noreferrer noopener">@XojoES</a> or on the <a href="https://forum.xojo.com/u/javier_menendez/summary" target="_blank" rel="noreferrer noopener">Xojo Forum</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Creating Libraries that Support Multiple Project Types</title>
		<link>https://blog.xojo.com/2025/12/09/creating-libraries-that-support-multiple-project-types/</link>
		
		<dc:creator><![CDATA[Geoff Perlman]]></dc:creator>
		<pubDate>Tue, 09 Dec 2025 16:31:12 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[2025r3]]></category>
		<category><![CDATA[LibMerge]]></category>
		<category><![CDATA[Libraries]]></category>
		<category><![CDATA[Multi-Platform Development]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15588</guid>

					<description><![CDATA[Libraries, introduced in Xojo 2025r3, make it easy to reuse your classes and interface items such as windows, webpages, and mobile screens across projects. As&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Libraries, introduced in Xojo 2025r3, make it easy to reuse your classes and interface items such as windows, webpages, and mobile screens across projects. As compiled code, Libraries ensure your projects always use a specific version of your functionality while allowing you to share features with other Xojo users without exposing your intellectual property. Think of them like plugins written in Xojo instead of C++, with the flexibility to use them in a single project folder or in the Plugins folder for access across all projects. The Xojo documentation provides guidance on <a href="https://documentation.xojo.com/topics/code_management/sharing_code_among_multiple_projects.html" target="_blank" rel="noreferrer noopener">creating your own Libraries</a>.</p>



<p>When you create a Library in Xojo, it’s tailored to the project type you’re working in, whether that is Desktop, Web, Mobile or Console, so everything stays organized and easy to manage. The Library format was designed to support all project types simultaneously; unfortunately, the Xojo IDE was not. The good news is that there are still ways to take advantage of the flexible underlying format. Since Libraries are simply .zip files, you can change the extension to .zip and decompress them to explore their contents. Inside, you’ll find a folder named for the project type you originally created it from, making it easy to understand the structure. Here are two ways to create Libraries that support multiple project types.</p>



<h2 class="wp-block-heading"><strong>Merging Libraries Manually</strong></h2>



<p>To manually create a multi-project-type Library, start by building a separate Library for each project type your functionality supports, then change each one’s extension to .zip and decompress it. Choose one decompressed Library to serve as the final version, and copy the project-type folders (Desktop, Web, iOS, Android or Console) from the others into it. When everything is combined, recompress the folder back into a .zip file and change the extension to .xojo_library. You now have a single Library that works across all the project types you included.</p>



<h2 class="wp-block-heading">Using LibMerge</h2>



<p>LibMerge is a utility we created to make it easier to merge Libraries.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="561" src="https://blog.xojo.com/wp-content/uploads/2025/11/LibMerge-1-1024x561.jpg" alt="" class="wp-image-15597" srcset="https://blog.xojo.com/wp-content/uploads/2025/11/LibMerge-1-1024x561.jpg 1024w, https://blog.xojo.com/wp-content/uploads/2025/11/LibMerge-1-300x165.jpg 300w, https://blog.xojo.com/wp-content/uploads/2025/11/LibMerge-1-768x421.jpg 768w, https://blog.xojo.com/wp-content/uploads/2025/11/LibMerge-1.jpg 1200w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<ol class="wp-block-list">
<li>Download LibMerge for <a href="https://blog.xojo.com/wp-content/uploads/2025/12/LibMergeLinux.zip" data-type="attachment" data-id="15691" target="_blank" rel="noreferrer noopener">Linux</a>, <a href="https://blog.xojo.com/wp-content/uploads/2025/12/LibMergeMac.zip" data-type="attachment" data-id="15693" target="_blank" rel="noreferrer noopener">macOS</a> or <a href="https://blog.xojo.com/wp-content/uploads/2025/12/LibMergeWindows.zip" data-type="attachment" data-id="15692" target="_blank" rel="noreferrer noopener">Windows</a>. It will be included in the Extras folder in the next major release.</li>



<li>Launch LibMerge and then click the Add button to select the Libraries you wish to merge or drag them into the Libraries list in the LibMerge window.</li>



<li>On the Info tab, make sure the Version, Copyright and Description values are as you want them for the merged Library. These initial values are loaded from the first Library you add to the list.</li>



<li>Click the Save As button to choose a name and location for your merged Library. That&#8217;s it!</li>
</ol>



<p>If you choose two libraries that both already support the same project type, LibMerge will tell you and not load the second Library. Included with LibMerge is the LibMerge Library which you can use to build the merging of Libraries into your own build tools. Check out the included LibMerge API Guide for details. Here is an example:</p>



<pre class="wp-block-code"><code>Try
   Var merge As New LibMerger
   merge.AddLibrary(SpecialFolder.Desktop.Child("MyDesktopLibrary.xojo_library"))
   merge.AddLibrary(SpecialFolder.Desktop.Child("MyWebLibrary.xojo_library"))
   merge.SaveMergedLibrary(SpecialFolder.Desktop.Child("MergedLibrary.xojo_library"))
Catch error as UnsupportedFormatException
   System.Beep
   MessageBox(error.Message)
End Try</code></pre>



<p>Whether you prefer to roll up your sleeves and merge Libraries manually or let LibMerge handle the heavy lifting, Xojo gives you the flexibility to build reusable components that work across all your project types. With a little exploration and the right tools you can streamline your workflow, reduce duplication and keep your projects cleaner and more maintainable. LibMerge makes this process fast and reliable whether you’re merging two Libraries or twenty. Read more about <a href="https://documentation.xojo.com/topics/code_management/sharing_code_among_multiple_projects.html" target="_blank" rel="noreferrer noopener">Libraries</a> in the Xojo Documentation.</p>



<p><em>Geoff Perlman is the Founder and CEO of Xojo. When he’s not leading the Xojo team he can be found playing drums in Austin, Texas and spending time with his family.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Modern and Evolving: macOS and iOS 26 and WinUI in Xojo</title>
		<link>https://blog.xojo.com/2025/12/09/modern-and-evolving-macos-and-ios-26-and-winui-in-xojo/</link>
		
		<dc:creator><![CDATA[Geoff Perlman]]></dc:creator>
		<pubDate>Tue, 09 Dec 2025 16:30:56 +0000</pubDate>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[2025r3]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[macOS 26]]></category>
		<category><![CDATA[macOS Tahoe]]></category>
		<category><![CDATA[UI]]></category>
		<category><![CDATA[WinUI]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15650</guid>

					<description><![CDATA[As the platforms we develop for continue to evolve, so does Xojo. Each year brings new design directions, updated frameworks and refreshed user experience standards&#8230;]]></description>
										<content:encoded><![CDATA[
<p>As the platforms we develop for continue to evolve, so does Xojo. Each year brings new design directions, updated frameworks and refreshed user experience standards across macOS, iOS and Windows. Staying aligned with these changes is essential, not just to keep apps looking modern, but to ensure they feel right at home on every device. In this post, we’ll take a look at how Xojo is adapting to Apple’s latest updates and our ongoing work to bring a modern Windows experience through WinUI.</p>



<h2 class="wp-block-heading">macOS 26 and iOS 26</h2>



<p>Over time, Apple has brought the user experiences of macOS and iOS closer together. macOS 26 and iOS 26, now aligned in version numbers, also share more similarities than ever in their user experience. These updates represent the most significant user experience changes from Apple since iOS was introduced in 2007 and Aqua for macOS seven years earlier. With such a big update, especially when designing elements to work on both large computers displays as well as small smartphone screens, it’s no surprise there’s some tweaking requiring after release. Clearly, Apple is still refining its platforms.</p>



<p>We continue to update Xojo as Apple defines its preferred user experience, ensuring that you can deliver the best possible experience to your users.</p>



<h2 class="wp-block-heading">WinUI</h2>



<p>We are also hard at work upgrading our Windows framework to WinUI, providing a modern user experience for Windows apps. You can see our progress in each release by enabling the Use WinUI (Experimental) option on the Advanced tab in Windows build settings. The “Experimental” label is a reminder that the feature is still evolving, and it will be removed once WinUI is fully ready. Our goal has always been to keep Xojo on a steady path, prepared for whatever challenges lie ahead.</p>



<h2 class="wp-block-heading">Conclusion</h2>



<p>On behalf of the entire Xojo team, I can say that we love what we do and we appreciate your support in allowing us to do it. We are Xojo users ourselves (after all, we make Xojo with Xojo) and we enjoy seeing what you make with it. With that in mind, feel free to tell us about your creations. Send your screenshots, descriptions and your story to hello@xojo.com.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>New WebUserAuthentication Control: Look, Mom, No Passwords!</title>
		<link>https://blog.xojo.com/2025/12/09/new-webuserauthentication-control-look-mom-no-passwords/</link>
		
		<dc:creator><![CDATA[Ricardo Cruz]]></dc:creator>
		<pubDate>Tue, 09 Dec 2025 16:30:29 +0000</pubDate>
				<category><![CDATA[Learning]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[2025r3]]></category>
		<category><![CDATA[Authentication]]></category>
		<category><![CDATA[Passkey]]></category>
		<category><![CDATA[Passwords]]></category>
		<category><![CDATA[webdev]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15321</guid>

					<description><![CDATA[The web framework has a new control available in the Library, WebUserAuthentication. Now that Passkeys have arrived, let&#8217;s explore this feature! Passkeys Demo In this&#8230;]]></description>
										<content:encoded><![CDATA[
<p>The web framework has a new control available in the Library, <code>WebUserAuthentication</code>. Now that Passkeys have arrived, let&#8217;s explore this feature!</p>



<h2 class="wp-block-heading">Passkeys Demo</h2>



<p>In this demo, we will be creating a new account using just our email. Using a platform authenticator, like Apple Passkeys or Windows Hello will make this pretty easy. They are integrated in the operating system and synced across devices. I will be using macOS with the integrated Passwords app, but this is supported in Windows through Windows Hello, or you could store, sync and use Passkeys using a Google Chrome Profile.</p>



<figure class="wp-block-video"><video height="1240" style="aspect-ratio: 1472 / 1240;" width="1472" controls src="https://blog.xojo.com/wp-content/uploads/2025/08/passkeys-passwordless-signup.mp4"></video></figure>



<p>As you can see, there is no intermediate step. No need to use a separate app to store your passwords securely. A Passkey will be generated and stored in the authenticator in one simple step. This Passkey will be automatically synced across devices and available on my iPhone.</p>



<p>Opening the Password application, I already can confirm my new Passkey has been stored for &#8220;localhost&#8221;. Notice the user name is also there, meaning you won&#8217;t need to fill it during the login process.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="710" src="https://blog.xojo.com/wp-content/uploads/2025/08/passkeys-in-password-app-1024x710.png" alt="" class="wp-image-15323" srcset="https://blog.xojo.com/wp-content/uploads/2025/08/passkeys-in-password-app-1024x710.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/08/passkeys-in-password-app-300x208.png 300w, https://blog.xojo.com/wp-content/uploads/2025/08/passkeys-in-password-app-768x533.png 768w, https://blog.xojo.com/wp-content/uploads/2025/08/passkeys-in-password-app-1536x1065.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/08/passkeys-in-password-app.png 1716w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>The username isn&#8217;t important or even required, it&#8217;s just to display a friendly name for this user. A Passkey will include the user ID, which can be any arbitrary String you want. In my example, I&#8217;ve used the new <a href="https://documentation.xojo.com/api/math/random.html#random-uuid" target="_blank" rel="noreferrer noopener">Random.UUID method</a>, but this is completely up to you. And this is transparent for the end user.</p>



<p>Now, let&#8217;s try to login:</p>



<figure class="wp-block-video"><video height="1240" style="aspect-ratio: 1472 / 1240;" width="1472" controls src="https://blog.xojo.com/wp-content/uploads/2025/08/passkeys-passwordless-signin.mp4"></video></figure>



<p>That&#8217;s it!</p>



<p>Another thing to notice is, while I have several Passkeys for different websites, only the relevant Passkey can be used. This makes Phishing attacks useless. End users won&#8217;t be able to use a Passkey anywhere else, just on the website where it has been created. And also, users won&#8217;t be able to send their password by mistake to an attacker because … they can&#8217;t!</p>



<p>For web application developers, another interesting thing to note is that you won&#8217;t be able to store a Passkey insecurely. Even if your database gets compromised, a hacker won&#8217;t be able to use the stored public keys to authenticate those users with another service. To make it easier to understand, you will be storing a lock, not the key used to open it.</p>



<h2 class="wp-block-heading">Other User Journeys</h2>



<p>My demo is just the classic email / password sign up / sign in workflow, but without using a password. Passkeys is based on WebAuthn (part of FIDO2) and there are several ways you can use this technology in your web application. For example, you could use a shared computer and still be able to securely log in using your mobile. The platform will display a QR code you can read with your phone camera, and grant the access from your personal device.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="889" src="https://blog.xojo.com/wp-content/uploads/2025/08/Sign-In-1024x889.png" alt="" class="wp-image-15325" srcset="https://blog.xojo.com/wp-content/uploads/2025/08/Sign-In-1024x889.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/08/Sign-In-300x260.png 300w, https://blog.xojo.com/wp-content/uploads/2025/08/Sign-In-768x666.png 768w, https://blog.xojo.com/wp-content/uploads/2025/08/Sign-In-1536x1333.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/08/Sign-In.png 1604w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>In my example application, the user can sign up using different emails. If the Passwords app encounters more than one for my domain it will allow the user to specify the Passkey to use:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="889" src="https://blog.xojo.com/wp-content/uploads/2025/08/o2-baieeamele.com_-1024x889.png" alt="" class="wp-image-15326" srcset="https://blog.xojo.com/wp-content/uploads/2025/08/o2-baieeamele.com_-1024x889.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/08/o2-baieeamele.com_-300x260.png 300w, https://blog.xojo.com/wp-content/uploads/2025/08/o2-baieeamele.com_-768x666.png 768w, https://blog.xojo.com/wp-content/uploads/2025/08/o2-baieeamele.com_-1536x1333.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/08/o2-baieeamele.com_.png 1604w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Xojo will take care of preparing the <code>WebAuthn</code> steps, verifying signatures and doing the common busy work for you. You will have to decide which workflow makes sense for your application and perform any further verifications, like sending a verification email on register, to ensure this user owns that account.</p>



<h2 class="wp-block-heading">Multi-Factor Authentication</h2>



<p>If you already require your users to authenticate with a username (or email) and a password, you could use <code>WebUserAuthentication</code> as a second factor. That means the user will need to provide something this person knows (a username and password combination) in addition to something the user has (the authenticator device)</p>



<p>Other common multi-factor authentication schemes are email magic links and time-based one-time passwords, <em>&#8220;TOTP&#8221;</em>.</p>



<p>More factors equal better security, of course. But as usual when it comes to security, you&#8217;ll have to find the sweet spot between secure and comfortable.</p>



<h2 class="wp-block-heading">Usernameless + Passwordless Authentication … Wait, What?!?</h2>



<p><em>&#8220;How can I authenticate without providing my username or email?&#8221;</em>. This is where real new possibilities arise. When you use a username with a password that only Chuck Norris and you know, this becomes a &#8220;proof of identity&#8221; (at least in theory, in practice a hacker could compromise an account using a weak password)</p>



<p>When using an authenticator without a username or password, it becomes a &#8220;proof of possession&#8221; of the authenticator device.</p>



<p>Again, think about it as a locker&#8217;s lock and a key. Everyone can see the lock, but only people with the correct key can open it. The public key would be the door&#8217;s lock, while the authenticator device would be the key. You can share the key with another person you trust to grant this person access to the contents behind that door. The difference with a real-life lock is that we will be using a really secure one, with a security key.</p>



<p>As long as you can proof you have a valid &#8220;key&#8221; to authenticate, you are granted to continue.</p>



<p>Consider the following scenario. The company could have a web application that uses a traditional username + password authentication but, for really special activities, the user needs to authenticate with a physical USB key authenticator device that is shared by everyone in the office.</p>



<p>Other use cases are obviously when privacy is involved. A private journal, or a private blogging service, voting. The inconvenience in this case is the user won&#8217;t be able to recover the account if they lose access to the authenticator. In this case, you might want to offer a different recovery solution, like printing a very long recovery code. If they also lose the recovery code, they will permanently lose the account.</p>



<h2 class="wp-block-heading">How To Use The New Control</h2>



<p>As you do with any other non-visual control, like a <code>WebTimer</code>, you can just drop the new <code>WebUserAuthentication</code> control into your WebPage.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="491" src="https://blog.xojo.com/wp-content/uploads/2025/08/webauthentication-dropping-into-webpage-1024x491.png" alt="" class="wp-image-15327" srcset="https://blog.xojo.com/wp-content/uploads/2025/08/webauthentication-dropping-into-webpage-1024x491.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/08/webauthentication-dropping-into-webpage-300x144.png 300w, https://blog.xojo.com/wp-content/uploads/2025/08/webauthentication-dropping-into-webpage-768x368.png 768w, https://blog.xojo.com/wp-content/uploads/2025/08/webauthentication-dropping-into-webpage-1536x736.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/08/webauthentication-dropping-into-webpage-2048x982.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Then configure its properties. The most important one is the Domain field. It must match the domain name where your application will be deployed. If you want to test it locally without using HTTPS, it must be &#8220;localhost&#8221; (&#8220;127.0.0.1&#8221; won&#8217;t work)</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="666" height="269" src="https://blog.xojo.com/wp-content/uploads/2025/08/Appearance-copia.png" alt="" class="wp-image-15328" srcset="https://blog.xojo.com/wp-content/uploads/2025/08/Appearance-copia.png 666w, https://blog.xojo.com/wp-content/uploads/2025/08/Appearance-copia-300x121.png 300w" sizes="auto, (max-width: 666px) 100vw, 666px" /></figure>



<p>There are four events available:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="656" height="250" src="https://blog.xojo.com/wp-content/uploads/2025/11/Captura-de-pantalla-2025-11-20-a-las-10.50.33.png" alt="" class="wp-image-15544" srcset="https://blog.xojo.com/wp-content/uploads/2025/11/Captura-de-pantalla-2025-11-20-a-las-10.50.33.png 656w, https://blog.xojo.com/wp-content/uploads/2025/11/Captura-de-pantalla-2025-11-20-a-las-10.50.33-300x114.png 300w" sizes="auto, (max-width: 656px) 100vw, 656px" /></figure>



<p>You can use <code>RegistrationSucceeded</code> and <code>AuthenticationSucceeded</code> to interact with your Database, store the details and redirect the user to their dashboard.</p>



<p>In <code>RegistrationSucceeded</code>, a <code>WebAuthenticationCredential</code> will be given to you. This is a data transfer object with the following properties you need to store in your database:</p>



<ul class="wp-block-list">
<li>ID</li>



<li>PublicKey</li>



<li>AuthenticationAttempts</li>



<li>DisplayName</li>
</ul>



<p>Error will be fired when something goes wrong. A message will also show with the details about what happened, but it isn&#8217;t meant to be shared with the end user. During the sign up and sign in processes, you should display generic messages for security, to avoid letting bad actors know what&#8217;s going on. If you need to inform the user something related to these messages, you can send them an automated email instead.</p>



<p><code>CredentialRequested</code> will be fired during the authentication ceremony. A userId and a credentialId will be given to you, and you should return a new <code>WebAuthenticationCredential</code> instance with the details coming from the <code>RegistrationSucceededEvent</code>.</p>



<p>Also, when <code>AuthenticationSucceeded</code> happens, the event will come with an <code>authenticationAttempts</code> parameter. This will be an incremental value used to update your credentials. This is part of the <code>WebAuthn</code> protocol sign in ceremony used to detect cloned authenticators, which is supported by Xojo. Please notice this value might come always as &#8220;0&#8221; when using Safari, for example, but Google Chrome will increase its value each time.</p>



<p>You can initiate a Registration or Authentication ceremony by calling Register or Authenticate, respectively.</p>



<ul class="wp-block-list">
<li><strong>Register</strong>(userId As String, username As String = &#8220;&#8221;, displayName As String = &#8220;&#8221;)<br>The parameter userId is required, the new credential will be built specifically for it. It can be anything that makes sense in your application, like an auto-incremental number or a random UUID . The other parameters are meant for giving the credential a friendly name. The username could be a nickname, or an email. In workflows where you allow the user to store more than one passkey, the displayName could be something like &#8220;Backup key&#8221;.</li>



<li><strong>Authenticate</strong>(Optional allowCredentials() As String)<br>This will initiate the authentication ceremony. You can optionally pass an array of credential IDs, allowed for the user trying to get access to the protected resource.</li>
</ul>



<h2 class="wp-block-heading">Adoption and Compatibility</h2>



<p>Not every user may know they even exist, what they are, how they work or if they will be more secure than using their pet&#8217;s name and birthdate. This can cause some friction. Other users that adopted the usage from day one might have at least two physical USB keys. They expect your application to allow them to enter more than one, just in case they lose their main USB key.</p>



<p>Passkeys are here to stay and their adoption will continue growing on web services. That said, depending on the combination of operating system and browser, there are some gotchas. Google Chrome or Firefox should work on every operating system. Apple users will probably obtain the best user experience if they&#8217;re tied to this ecosystem. Linux users using alternative browsers could experience some challenges.</p>



<p>If compatibility is a must for your application, you should still offer an alternative to Passkeys. For example, legacy passwords, or &#8220;magic login links&#8221; sent by email.</p>



<h2 class="wp-block-heading">Wrapping Up</h2>



<p>We are sure Passkeys will be the norm in the coming years. Read more in the <a href="https://documentation.xojo.com/api/web/webauthenticationcredential.html" target="_blank" rel="noreferrer noopener">Xojo Docs</a>. Xojo is ready to embrace them and you can start adopting them in your Xojo Web application today!</p>



<p><em>Ricardo has always been curious about how things work. Growing up surrounded by computers</em> he became interested in <em>web technologies in the dial-up connections era. Xojo has been his secret weapon and language of preference since 2018. When he’s not online, chances are he will be scuba diving … or crocheting amigurumis. Find Ricardo on Twitter <a href="https://web.archive.org/web/20220805000833/https://www.twitter.com/piradoiv" target="_blank" rel="noreferrer noopener">@piradoiv</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2025/08/passkeys-passwordless-signup.mp4" length="684699" type="video/mp4" />
<enclosure url="https://blog.xojo.com/wp-content/uploads/2025/08/passkeys-passwordless-signin.mp4" length="435817" type="video/mp4" />

			</item>
		<item>
		<title>Toward the Future with WinUI</title>
		<link>https://blog.xojo.com/2025/12/09/toward-the-future-with-winui/</link>
		
		<dc:creator><![CDATA[William Yu]]></dc:creator>
		<pubDate>Tue, 09 Dec 2025 16:30:10 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[2025r3]]></category>
		<category><![CDATA[DesktopXAMLContainer]]></category>
		<category><![CDATA[WinUI]]></category>
		<category><![CDATA[XAML]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15618</guid>

					<description><![CDATA[Keeping up with innovation can be challenging, especially when new technologies don&#8217;t always align neatly with what came before. Microsoft works hard to find a&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Keeping up with innovation can be challenging, especially when new technologies don&#8217;t always align neatly with what came before. Microsoft works hard to find a balance, they experiment, iterate, and refine to discover what their users really want.</p>



<p>We&#8217;re taking a similar approach with our WinUI transition. We began with the <a href="https://blog.xojo.com/2023/08/09/doing-more-with-desktopxamlcontainer/" target="_blank" rel="noreferrer noopener">DesktopXAMLContainer</a> and are continuing by updating our <a href="https://blog.xojo.com/2025/07/08/a-xaml-driven-ui/" target="_blank" rel="noreferrer noopener">Win32 controls to their WinUI counterparts</a>, aiming for steady progress without disrupting existing workflows.</p>



<h3 class="wp-block-heading">What can you look forward to in 2025r3?</h3>



<p>We&#8217;ve expanded our WinUI offerings in this release with a broader set of updated controls. While 2025r2 introduced only a handful of WinUI-backed controls, 2025r3 builds on that foundation by updating a much larger group, including: BevelButton, Label, UpDownArrow, DateTimePicker, ComboBox, PopupMenu, RadioGroup, SegmentedButton, DisclosureTriangle, MoviePlayer, SearchField, TextField, and TextArea.</p>



<h3 class="wp-block-heading">What are the benefits of using WinUI?</h3>



<p>Win32 controls have been the foundation for many Windows apps, but WinUI introduces capabilities that traditional Win32 controls don&#8217;t have. Here&#8217;s a comparison to highlight some of the differences:</p>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-media-text is-stacked-on-mobile" style="grid-template-columns:20% auto"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="84" height="33" src="https://blog.xojo.com/wp-content/uploads/2025/12/Win32Label.png" alt="" class="wp-image-15619 size-full"/></figure><div class="wp-block-media-text__content">
<p>A Win32 DesktopLabel with a colored emoji is rendered in black and white.</p>
</div></div>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-media-text is-stacked-on-mobile" style="grid-template-columns:20% auto"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="79" height="32" src="https://blog.xojo.com/wp-content/uploads/2025/12/WinUILabel-1.png" alt="" class="wp-image-15627 size-full"/></figure><div class="wp-block-media-text__content">
<p>Compared to the WinUI version with a colored emoji.</p>
</div></div>
</div>
</div>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-media-text is-stacked-on-mobile" style="grid-template-columns:30% auto"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="167" height="49" src="https://blog.xojo.com/wp-content/uploads/2025/12/Win32TextField.png" alt="" class="wp-image-15628 size-full"/></figure><div class="wp-block-media-text__content">
<p>A Win32 DesktopTextField containing right-to-left text isn&#8217;t automatically recognized as such, so it renders left-to-right.</p>
</div></div>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-media-text is-stacked-on-mobile" style="grid-template-columns:30% auto"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="167" height="49" src="https://blog.xojo.com/wp-content/uploads/2025/12/WinUITextField.png" alt="" class="wp-image-15629 size-full"/></figure><div class="wp-block-media-text__content">
<p>Compared to the WinUI version which can automatically detect right-to-left text and formats accordingly.</p>
</div></div>
</div>
</div>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-media-text is-stacked-on-mobile" style="grid-template-columns:30% auto"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="167" height="49" src="https://blog.xojo.com/wp-content/uploads/2025/12/Win32PasswordField.png" alt="" class="wp-image-15631 size-full"/></figure><div class="wp-block-media-text__content">
<p>A password field (via DesktopTextField) with primitive support on Win32.</p>
</div></div>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-media-text is-stacked-on-mobile" style="grid-template-columns:30% auto"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="167" height="49" src="https://blog.xojo.com/wp-content/uploads/2025/12/WinUIPasswordField.png" alt="" class="wp-image-15632 size-full"/></figure><div class="wp-block-media-text__content">
<p>An actual WinUI version of their PasswordBox control with a preview widget.</p>
</div></div>
</div>
</div>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-media-text is-stacked-on-mobile" style="grid-template-columns:30% auto"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="179" height="203" src="https://blog.xojo.com/wp-content/uploads/2025/12/Win32ComboBox.png" alt="" class="wp-image-15633 size-full"/></figure><div class="wp-block-media-text__content">
<p>A Win32 DesktopComboBox which does not support separators.</p>
</div></div>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-media-text is-stacked-on-mobile" style="grid-template-columns:30% auto"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="189" height="356" src="https://blog.xojo.com/wp-content/uploads/2025/12/WinUIComboBox.png" alt="" class="wp-image-15634 size-full" srcset="https://blog.xojo.com/wp-content/uploads/2025/12/WinUIComboBox.png 189w, https://blog.xojo.com/wp-content/uploads/2025/12/WinUIComboBox-159x300.png 159w" sizes="auto, (max-width: 189px) 100vw, 189px" /></figure><div class="wp-block-media-text__content">
<p>A more modern looking WinUI version with built-in support for separators. </p>
</div></div>
</div>
</div>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-media-text is-stacked-on-mobile"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="372" height="297" src="https://blog.xojo.com/wp-content/uploads/2025/12/Win32CalendarDatePicker.png" alt="" class="wp-image-15635 size-full" srcset="https://blog.xojo.com/wp-content/uploads/2025/12/Win32CalendarDatePicker.png 372w, https://blog.xojo.com/wp-content/uploads/2025/12/Win32CalendarDatePicker-300x240.png 300w" sizes="auto, (max-width: 372px) 100vw, 372px" /></figure><div class="wp-block-media-text__content">
<p>A Win32 DesktopDateTimePicker with a dropdown calendar, but does not support dark mode.</p>
</div></div>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-media-text is-stacked-on-mobile"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="463" height="542" src="https://blog.xojo.com/wp-content/uploads/2025/12/WinUICalendarDatePicker.png" alt="" class="wp-image-15636 size-full" srcset="https://blog.xojo.com/wp-content/uploads/2025/12/WinUICalendarDatePicker.png 463w, https://blog.xojo.com/wp-content/uploads/2025/12/WinUICalendarDatePicker-256x300.png 256w" sizes="auto, (max-width: 463px) 100vw, 463px" /></figure><div class="wp-block-media-text__content">
<p>A more modern looking WinUI version that also supports dark mode.</p>
</div></div>
</div>
</div>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-media-text is-stacked-on-mobile"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="576" height="350" src="https://blog.xojo.com/wp-content/uploads/2025/12/Win32DarkModeGlitches.png" alt="" class="wp-image-15637 size-full" srcset="https://blog.xojo.com/wp-content/uploads/2025/12/Win32DarkModeGlitches.png 576w, https://blog.xojo.com/wp-content/uploads/2025/12/Win32DarkModeGlitches-300x182.png 300w" sizes="auto, (max-width: 576px) 100vw, 576px" /></figure><div class="wp-block-media-text__content">
<p>Win32 dark mode support is limited.</p>
</div></div>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-media-text is-stacked-on-mobile"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="472" height="600" src="https://blog.xojo.com/wp-content/uploads/2025/12/WinUIDarkMode.png" alt="" class="wp-image-15638 size-full" srcset="https://blog.xojo.com/wp-content/uploads/2025/12/WinUIDarkMode.png 472w, https://blog.xojo.com/wp-content/uploads/2025/12/WinUIDarkMode-236x300.png 236w" sizes="auto, (max-width: 472px) 100vw, 472px" /></figure><div class="wp-block-media-text__content">
<p>WinUI dark mode support is easier on the eyes.</p>
</div></div>
</div>
</div>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-media-text is-stacked-on-mobile"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="642" height="554" src="https://blog.xojo.com/wp-content/uploads/2025/12/Win32MoviePlayer.png" alt="" class="wp-image-15639 size-full" srcset="https://blog.xojo.com/wp-content/uploads/2025/12/Win32MoviePlayer.png 642w, https://blog.xojo.com/wp-content/uploads/2025/12/Win32MoviePlayer-300x259.png 300w" sizes="auto, (max-width: 642px) 100vw, 642px" /></figure><div class="wp-block-media-text__content">
<p>The Win32 DesktopMoviePlayer is very dated.</p>
</div></div>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-media-text is-stacked-on-mobile"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="642" height="554" src="https://blog.xojo.com/wp-content/uploads/2025/12/WinUIMoviePlayer.png" alt="" class="wp-image-15640 size-full" srcset="https://blog.xojo.com/wp-content/uploads/2025/12/WinUIMoviePlayer.png 642w, https://blog.xojo.com/wp-content/uploads/2025/12/WinUIMoviePlayer-300x259.png 300w" sizes="auto, (max-width: 642px) 100vw, 642px" /></figure><div class="wp-block-media-text__content">
<p>WinUI has a much more modern look and feel.</p>
</div></div>
</div>
</div>



<h3 class="wp-block-heading">Opt-in to WinUI</h3>



<p>If you&#8217;d like to preview how your apps look and feel with WinUI controls, open the Windows build settings and check the options under the Advanced widget tab. Selecting&nbsp;<strong>“Use WinUI”</strong>&nbsp;applies WinUI styling to your desktop controls while keeping them scaled to your existing Win32 control bounds. Opting into&nbsp;<strong>“Native Control Sizes”</strong>&nbsp;gives you a more accurate representation of a true WinUI app, using the larger default font size and correspondingly larger controls.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="433" height="381" src="https://blog.xojo.com/wp-content/uploads/2025/12/WinUIBuildSettings.png" alt="" class="wp-image-15641" srcset="https://blog.xojo.com/wp-content/uploads/2025/12/WinUIBuildSettings.png 433w, https://blog.xojo.com/wp-content/uploads/2025/12/WinUIBuildSettings-300x264.png 300w" sizes="auto, (max-width: 433px) 100vw, 433px" /></figure>



<h3 class="wp-block-heading">More Work Ahead</h3>



<p>As we continue down this path, we&#8217;re uncovering pain points that developers face when using WinUI controls in a Win32 environment—challenges Microsoft is no doubt familiar with as well. It will take time before we can fully move away from Win32 controls/windows and embrace WinUI, but we&#8217;re steadily heading in that direction. Thanks for joining us on this experience, more to come!</p>



<p><em><em><em>William Yu grew up in Canada learning to program BASIC on a Vic-20. He is Xojo’s resident Windows and Linux engineer, among his many other skills. Some may say he has joined the dark side here in the USA, but he will always be a Canadian at heart.</em></em></em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Welcome to the Grid</title>
		<link>https://blog.xojo.com/2025/12/09/welcome-to-the-grid/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Tue, 09 Dec 2025 16:29:53 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[2025r3]]></category>
		<category><![CDATA[Grid Control]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15663</guid>

					<description><![CDATA[Xojo 2025r3 introduces the first iteration of the DesktopGrid control. This long-awaited control allows you to display as many rows and columns as needed, making&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Xojo 2025r3 introduces the first iteration of the DesktopGrid control. This long-awaited control allows you to display as many rows and columns as needed, making it ideal for complex data layouts. Let’s take a closer look at some of its features.</p>



<p>Like other controls in the Xojo framework, DesktopGrid is a data-source-based control. Instead of manually adding cells, rows, or columns as you would with a ListBox, the DesktopGrid itself requests the data it needs when it needs it. This approach brings several benefits:</p>



<p><strong>ContainerControl-based cells:</strong> The cells in a DesktopGrid are full ContainerControls, just like the ones you’re already familiar with. You can use the same layout for all cells or customize different layouts for individual cells, rows, or columns. Each cell represents a live control and behaves accordingly.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="741" src="https://blog.xojo.com/wp-content/uploads/2025/12/Captura-de-pantalla-2025-12-04-a-las-11.50.43-1024x741.png" alt="" class="wp-image-15666" srcset="https://blog.xojo.com/wp-content/uploads/2025/12/Captura-de-pantalla-2025-12-04-a-las-11.50.43-1024x741.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/12/Captura-de-pantalla-2025-12-04-a-las-11.50.43-300x217.png 300w, https://blog.xojo.com/wp-content/uploads/2025/12/Captura-de-pantalla-2025-12-04-a-las-11.50.43-768x556.png 768w, https://blog.xojo.com/wp-content/uploads/2025/12/Captura-de-pantalla-2025-12-04-a-las-11.50.43-1536x1112.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/12/Captura-de-pantalla-2025-12-04-a-las-11.50.43-2048x1483.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<ul class="wp-block-list">
<li><strong>Lower memory footprint:</strong> DesktopGrid keeps only the cells that are currently visible on screen “alive,” which significantly reduces memory usage, especially when working with very large data sets. For example, when you resize the containing window, the DesktopGrid will request additional content from its DataSource <strong>only if necessary</strong>. When cells move outside the visible area of the DesktopGrid, their corresponding ContainerControl instances are “closed,” triggering an event you can handle, and freeing the memory they were using.</li>



<li><strong>Faster execution</strong>: Large data sets are not preloaded into the control. This means that opening a window with a DesktopGrid or running an app with many cells happens almost instantly, providing a smooth and responsive experience even with extensive data.</li>
</ul>



<figure class="wp-block-video"><video height="1080" style="aspect-ratio: 1920 / 1080;" width="1920" controls src="https://blog.xojo.com/wp-content/uploads/2025/12/FastExecution.mp4"></video></figure>



<ul class="wp-block-list">
<li><strong>Layout Flexibility</strong>: Since the number of rows and columns is determined by the DataSource, a DesktopGrid instance can have a flexible layout rather than a rigid, static one. For example, you can adjust the number of columns based on the available width of the DesktopGrid. You can also set different widths for individual columns, while the row height remains fixed.</li>
</ul>



<figure class="wp-block-video"><video height="1080" style="aspect-ratio: 1920 / 1080;" width="1920" controls src="https://blog.xojo.com/wp-content/uploads/2025/12/FlexibleGridLayout.mp4"></video></figure>



<ul class="wp-block-list">
<li><strong>Data representation changes &#8220;on the fly&#8221;</strong>: Because the DataSource provides the content for each cell, you can dynamically change the data representation (the ContainerControl layout) at runtime or even pull data from a completely different source.</li>



<li><strong>A better separation of responsibilities</strong>: While you can implement the GridDataSource interface directly on the DesktopGrid or in its containing Window, using a dedicated DataSource class is the cleaner approach. This ensures a clearer separation between the view (the DesktopGrid), the model (the data feeding the cells), and the controller (which manages interactions between the two). A single DataSource can also feed multiple DesktopGrid instances, making your code more reusable.</li>



<li><strong>Headers everywhere:</strong> By default, DesktopGrid displays column and row headers. You can modify this in the Inspector Panel or via code. Depending on your scenario, you might choose to show both headers, just one, or hide them entirely. By default, the headers display simple numbering for each column and row. However, you can fully customize their content using the PaintHeaderContentForColumn and PaintHeaderContentForRow methods of your GridDataSource implementation, giving you complete control over how headers appear.</li>
</ul>



<h2 class="wp-block-heading">Is the DesktopGrid a replacement for DesktopListBox?</h2>



<p>While you can use DesktopGrid for many purposes, it is not a direct replacement for DesktopListBox in all scenarios. If your data is primarily textual (like simple labels) or relies on features specific to DesktopListBox, such as hierarchical data representation, then DesktopListBox is still the better choice.</p>



<p>DesktopGrid shines in scenarios where you need complex layouts in each cell using live controls rather than temporary pictures or workarounds. Each cell can have its own layout, including interactive controls such as ListBoxes, buttons, or other reactive elements that respond to user interactions. This makes DesktopGrid ideal for rich, interactive, and highly customizable grid layouts.</p>



<h2 class="wp-block-heading">Performance Caveats to Consider</h2>



<p>Although the first iteration of DesktopGrid was designed with performance in mind, there are some factors that may affect its redraw speed. The most significant is that each cell uses live controls, so performance will be similar to placing the same number of controls directly on a Window. While alternative approaches—such as reusable cells or backing picture representations—could improve speed, they come with their own trade-offs.</p>



<p>As a general rule, performance depends on cell size and the number of visible cells at any given time. A large DesktopGrid with many rows and columns, even if each cell contains just a simple label, may experience slower refresh rates. Additionally, actual performance can vary depending on the operating system and its version, as these affect the underlying drawing and refresh processes.</p>



<h2 class="wp-block-heading">Wiring the Grid</h2>



<p>Although this is just the first iteration of the DesktopGrid control, we are already working on the next set of features while further refining the existing ones. You can read more about this control in the <a href="https://documentation.xojo.com/api/user_interface/desktop/desktopgrid.html" target="_blank" rel="noreferrer noopener">Xojo Documentation</a>. We want to extend a big <strong>THANK YOU</strong> to everyone who provided feedback and dedicated their time testing the Grid during the beta cycle, you know who you are! Your input is invaluable, and the feature requests you submitted (combined with others already on our roadmap) will help shape a DesktopGrid that better fits your needs.</p>



<p><em>Javier Menendez is an engineer at Xojo and has been using Xojo since 1998. He lives in Castellón</em>, <em>Spain and hosts regular Xojo hangouts en español. Ask Javier questions on Twitter at <a href="https://twitter.com/xojoes" target="_blank" rel="noreferrer noopener">@XojoES</a> or on the <a href="https://forum.xojo.com/u/javier_menendez/summary" target="_blank" rel="noreferrer noopener">Xojo Forum</a>.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2025/12/FastExecution.mp4" length="432356" type="video/mp4" />
<enclosure url="https://blog.xojo.com/wp-content/uploads/2025/12/FlexibleGridLayout.mp4" length="2560805" type="video/mp4" />

			</item>
		<item>
		<title>Checking Out Xojo Libraries</title>
		<link>https://blog.xojo.com/2025/12/09/checking-out-xojo-libraries/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Tue, 09 Dec 2025 16:29:31 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[2025r3]]></category>
		<category><![CDATA[Console]]></category>
		<category><![CDATA[Libraries]]></category>
		<category><![CDATA[Rapid Application Development]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15569</guid>

					<description><![CDATA[The ability to create a compiled Library with Xojo has been a long-requested feature. Starting with 2025 Release 3, Library support is now available as&#8230;]]></description>
										<content:encoded><![CDATA[
<p>The ability to create a compiled Library with Xojo has been a long-requested feature. Starting with 2025 Release 3, Library support is now available as a preview. Here’s more information about what it is and how you can use it.</p>



<h2 class="wp-block-heading">What is a Library?</h2>



<p>A Library is a collection of pre-written, reusable code containing methods, classes and UI.&nbsp;Up until now, the way to distribute a Library for use with Xojo was to create a Plugin or to manually re-use project items across projects. Both have pros and cons.</p>



<p>Plugins are compiled and do not expose source code, but plugins cannot be created using Xojo itself and are typically created using C/C++ along with the Xojo Plugin SDK. Sharing project items is fine for internal projects or open-source projects, but less ideal for commercial libraries. They can be harder to manually add to a project and are recompiled along with the project, slowing the debug process.</p>



<p>With a Xojo Library, you can now create your own compiled Library using Xojo itself. This Library can contain nearly any Xojo project item and can be easily used in other Xojo projects because it is distributed as a single file.</p>



<p>At a high-level, you create your Library in Xojo, add your project items to it and built it into a Library package file. Other projects can then use this Library package, which gives them access to the items you included in the Library.</p>



<h2 class="wp-block-heading">Creating a Library</h2>



<p>Here is a brief overview of how you create a Xojo Library:</p>



<ol class="wp-block-list">
<li>In a Desktop, Web, Console or iOS project add a Library by choosing Insert-&gt;Library.</li>



<li>Add the project items you want to the Library. Any Xojo project item is supported, except for Worker.</li>



<li>Build the project. It will build the main app (which should serve as a test app for your Library) and a separate Library package file (with extension .xojo_library).</li>



<li>You can put this Library package alongside another project (on the drive) and it will be loaded when that project is opened by Xojo. You can then use the classes, methods and UI contained in the Library within your project. If you instead put the Library in the Plugins folder, then it will be available for all projects.</li>
</ol>



<p>This is all best demonstrated by a quick example. Go ahead and create a Desktop project and add a Library to it, which adds a Library1 project item to the Navigator. Change its name using the Inspector to LibHello.</p>



<p>While LibHello is selected, choose Insert-&gt;Class. This adds Class1 to it. This new class is now part of the Library. With Class1 selected, change its name to StringStuff.</p>



<p>You can now add whatever methods or properties you want to the class. For our example purposes here we will add a simple method that reverses a string.</p>



<pre class="wp-block-code"><code>Public Function ReverseString(s As String) As String
  Var newString As String
  
  For Each c As String In s.Characters
    newString = c + newString
  Next
  
  Return newString
End Function</code></pre>



<p>The Library could contain many other things of course, but to keep things simple this Library will have just the single class with its single method. Here&#8217;s what it looks like in the project:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="311" src="https://blog.xojo.com/wp-content/uploads/2025/11/CleanShot-2025-11-25-at-10.13.55@2x-1024x311.png" alt="" class="wp-image-15570" srcset="https://blog.xojo.com/wp-content/uploads/2025/11/CleanShot-2025-11-25-at-10.13.55@2x-1024x311.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/11/CleanShot-2025-11-25-at-10.13.55@2x-300x91.png 300w, https://blog.xojo.com/wp-content/uploads/2025/11/CleanShot-2025-11-25-at-10.13.55@2x-768x233.png 768w, https://blog.xojo.com/wp-content/uploads/2025/11/CleanShot-2025-11-25-at-10.13.55@2x.png 1382w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>The first thing to do is to test this Library ReverseString method. Add a button to Window1 and have it call the function, verifying the result.</p>



<pre class="wp-block-code"><code>Var stuff As New StringStuff
Var result As String = stuff.ReverseString("Xojo")

MessageBox(result)</code></pre>



<p>When you run, you can see the output:</p>



<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" width="744" height="584" src="https://blog.xojo.com/wp-content/uploads/2025/11/CleanShot-2025-11-25-at-10.15.21@2x.png" alt="" class="wp-image-15572" style="width:407px;height:auto" srcset="https://blog.xojo.com/wp-content/uploads/2025/11/CleanShot-2025-11-25-at-10.15.21@2x.png 744w, https://blog.xojo.com/wp-content/uploads/2025/11/CleanShot-2025-11-25-at-10.15.21@2x-300x235.png 300w" sizes="auto, (max-width: 744px) 100vw, 744px" /></figure>



<p>So far this is all not much different than you would normally be doing with a Xojo project. The next step is to create the Library package for use by other projects.</p>



<p>In the Build Settings area, select Shared. This is where you can enter some information about the Library that can be seen by those that use it.</p>



<ul class="wp-block-list">
<li>In the Version field, enter &#8220;1.0&#8221;.</li>



<li>In the Copyright field, enter &#8220;Acme, Inc.&#8221;</li>



<li>In the Description field, enter &#8220;A Xojo Library test.&#8221;</li>
</ul>



<p>Also in the Build Settings area, check the boxes for the platforms you want the Library to work on. In most situations, you will want to select macOS, Windows and Linux.</p>



<p>Now click Build. This builds the app as usual, but also creates a separate Library package file (LibHello.xojo_library for this example) that can be used with other projects.</p>



<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" width="1024" height="558" src="https://blog.xojo.com/wp-content/uploads/2025/11/FinderLibrary-1-1024x558.png" alt="" class="wp-image-15577" style="width:590px;height:auto" srcset="https://blog.xojo.com/wp-content/uploads/2025/11/FinderLibrary-1-1024x558.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/11/FinderLibrary-1-300x163.png 300w, https://blog.xojo.com/wp-content/uploads/2025/11/FinderLibrary-1-768x418.png 768w, https://blog.xojo.com/wp-content/uploads/2025/11/FinderLibrary-1-1536x837.png 1536w, https://blog.xojo.com/wp-content/uploads/2025/11/FinderLibrary-1.png 1542w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading">Using a Library</h2>



<p>Now that you&#8217;ve created your Library package, you can use it with other Xojo projects. The Library built above was created within a Desktop project, so it can only be used with other Desktop projects. So the first thing to do is to create a new Desktop project (call it MyTest), save it and close it.</p>



<p>Once it is saved, go to Finder or Explorer and place a copy of the LibHello.xojo_library file (from its build location) alongside this saved project file.</p>



<p>Go back to Xojo and open the MyTest project. The project will open normally, but the Library will also be loaded up as well. You can see this by showing the Xojo About window and going to the Plugins &amp; Libraries tab. There you will see the Library name along with the information you entered about it earlier. (Double-click on the Library row to show the description.)</p>



<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" width="1024" height="726" src="https://blog.xojo.com/wp-content/uploads/2025/11/AboutWindow-1024x726.png" alt="" class="wp-image-15578" style="width:664px;height:auto" srcset="https://blog.xojo.com/wp-content/uploads/2025/11/AboutWindow-1024x726.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/11/AboutWindow-300x213.png 300w, https://blog.xojo.com/wp-content/uploads/2025/11/AboutWindow-768x544.png 768w, https://blog.xojo.com/wp-content/uploads/2025/11/AboutWindow.png 1524w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Going back to the MyTest project, you can now use the Library with it. Add a button to the window and have it call the StringReverse function the same way you did before:</p>



<pre class="wp-block-code"><code>Var stuff As New StringStuff
Var result As String = stuff.ReverseString("Xojo")

MessageBox(result)</code></pre>



<p>Now run the project and it will use the class and its method just as if it is part of the project.</p>



<p>That&#8217;s the basics of how to create and use a Library. You can of course include whatever you want in the Library, but as with any library it is usually a good idea to keep things well-organized.</p>



<h2 class="wp-block-heading">Considerations</h2>



<ul class="wp-block-list">
<li>A Library package (which uses ZIP) contains compiled code and definitions of the public API in that code.</li>



<li>Only a single Library project item can be added to a project when developing.</li>



<li>A project can use any number of Library packages.</li>



<li>For a built library to work on all OS platforms, then those platforms must be selected before building it.</li>



<li>Libraries only support 64-bit builds.</li>



<li>Library packages are placed alongside the project file and are loaded when the project is loaded.</li>



<li>Library packages can also be placed in the Plugins folder. These libraries will be loaded separately for each project.</li>



<li>If items in your Library have dependencies outside the Library, then the Library package will not be usable in another project without those dependencies. For example, if a Library class method references a class in the main project, then it will build without an error (because the main project is available), but if you use that Library in another project you will get linker errors.</li>
</ul>



<h2 class="wp-block-heading">Why a Preview?</h2>



<p>We are referring to this initial version of Xojo Libraries as a preview release because it is very new and we want to give more developers a chance to test with it so we can iron out issues. We encourage you to try moving your existing reusable code collections over to a Library to help test, while also improving your workflow. If you have any open-source projects that are essentially a Library, you might try building them into a Xojo Library package as well.</p>



<p>You can make Library packages available publicly, but you should probably tag them as a preview, beta or test version until we remove the preview label.</p>



<p>Read more about Libraries in the <a href="https://documentation.xojo.com/topics/code_management/sharing_code_among_multiple_projects.html" target="_blank" rel="noreferrer noopener">Xojo Documentation</a>. Check out these open-source projects on GitHub that have recently been updated for API 2.0 and now have a Library that you can download from the Releases section:</p>



<ul class="wp-block-list">
<li><a href="https://github.com/xojo/VB" target="_blank" rel="noreferrer noopener">Visual Basic Library</a></li>



<li><a href="https://github.com/xojo/FM" target="_blank" rel="noreferrer noopener">FileMaker Library</a></li>



<li><a href="https://github.com/paullefebvre/winapilib" target="_blank" rel="noreferrer noopener">WinAPI Library</a></li>
</ul>



<p><em>Paul learned to program in BASIC at age 13 and has programmed in more languages than he remembers, with Xojo being an obvious favorite. When not working on Xojo, you can find him talking about retrocomputing at <a href="https://goto10.substack.com" target="_blank" rel="noreferrer noopener">Goto 10</a> and </em>on Mastodon @lefebvre@hachyderm.io.</p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Year of Code 2025: November Project – PDF Postcard Generator</title>
		<link>https://blog.xojo.com/2025/11/10/year-of-code-2025-november-project-pdf-postcard-generator/</link>
		
		<dc:creator><![CDATA[Gabriel Ludosanu]]></dc:creator>
		<pubDate>Mon, 10 Nov 2025 22:32:24 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Year of Code]]></category>
		<category><![CDATA[#YearofCode]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[PDF]]></category>
		<category><![CDATA[PDFDocument]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15499</guid>

					<description><![CDATA[For November&#8217;s Xojo Year of Code 2025, I’ve created a fun and practical project: a PDF Postcard Generator. This desktop application allows you to easily&#8230;]]></description>
										<content:encoded><![CDATA[
<p>For November&#8217;s Xojo Year of Code 2025, I’ve created a fun and practical project: a PDF Postcard Generator. This desktop application allows you to easily design personalized holiday postcards by combining a chosen image with a custom message, then exporting it as a ready-to-share PDF. It&#8217;s a fantastic way to see Xojo’s capabilities in handling graphics, file operations, and PDF creation, all within a simple, intuitive interface.</p>



<h2 class="wp-block-heading">What this project includes</h2>



<ul class="wp-block-list">
<li>A&nbsp;<code>DesktopWindow</code>&nbsp;(<code>wMain</code>) that provides a clean user interface for selecting an image, inputting your message, and generating the final PDF postcard.</li>



<li>Intelligent image handling that supports common formats like JPG, PNG, and GIF. The application automatically crops your selected image to a perfect 4:6 aspect ratio, ensuring it fits the postcard layout beautifully.</li>



<li>Robust PDF generation, leveraging Xojo&#8217;s&nbsp;<code>PDFDocument</code>&nbsp;and&nbsp;<code>Graphics</code>&nbsp;classes to embed images and render styled text effectively onto the document.</li>



<li>Customizable message rendering, which includes a subtle drop shadow effect for improved readability and a polished look against your background image.</li>



<li>Automated saving of the generated PDF postcard to your desktop, complete with a unique, timestamped filename, and immediate opening of the file in your system&#8217;s default viewer for quick review.</li>
</ul>



<h2 class="wp-block-heading">Download</h2>



<p>You can download the entire Xojo project from <a href="https://github.com/xolabsro/Holiday-Postcard-Generator" target="_blank" rel="noreferrer noopener">GitHub</a>.</p>



<p>This project illustrates Xojo&#8217;s robust capabilities for handling graphics and generating PDFs, demonstrating how straightforward it is to create functional and creative desktop applications. We encourage you to use this postcard generator as a springboard for your own ideas. Perhaps you could expand it by adding features like custom fonts, multiple message fields, or even integration with a data source for personalized bulk postcards. Or, consider how Xojo&#8217;s PDF features could power entirely new applications for reporting, invoicing, or custom document creation. We&#8217;d love to see what you build!</p>



<p><em>Gabriel is a digital marketing enthusiast who loves coding with Xojo to create cool software tools for any platform. He is always eager to learn and share new ideas!</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p><strong>Year of Code Project</strong></p>



<ul class="wp-block-list">
<li><a href="https://blog.xojo.com/2025/01/09/year-of-code-2025-kickoff/">Year of Code: Kickoff</a></li>



<li><a href="https://blog.xojo.com/2025/01/15/year-of-code-2025-january-project/" target="_blank" rel="noreferrer noopener">January Project: Desktop Apps</a>&nbsp;|&nbsp;<a href="https://forum.xojo.com/t/year-of-code-2025-january-project-sharing/83927" target="_blank" rel="noreferrer noopener">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/02/11/year-of-code-2025-february-project/">February Project: Database Apps</a>&nbsp;|&nbsp;<a href="https://forum.xojo.com/t/2025-year-of-code-february" target="_blank" rel="noreferrer noopener">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/03/05/year-of-code-2025-march-project-web-apps/">March Project: Web Apps</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-march/84474?u=alyssa_foley">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/04/08/year-of-code-2025-april-project-user-interface/">April Project: User Interface</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-april-user-interface/84926">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/05/07/year-of-code-2025-may-project-mobile-apps/">May Project: Mobile Apps</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-may-is-mobile/85272">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/06/10/year-of-code-2025-june-project-cross-platform-code-class/">June Project: Code Sharing</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-june-is-code-sharing/85612">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/07/10/year-of-code-2025-july-project-charting/">July Project: Charting</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-july-is-charting/85896">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/08/07/year-of-code-2025-august-project-console-apps/">August Project: Console Apps</a> | <a href="https://forum.xojo.com/t/august-2025-year-of-code-console-apps/86203">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/09/08/year-of-code-2025-september-project-games/">September Project: Games</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-septgamer">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/10/13/year-of-code-2025-october-project-multi-platform-communication/">October Project: Multi-Platform</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-october-multi-platform-communication/86717">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/11/10/year-of-code-2025-november-project-pdf-postcard-generator/">November Project: PDF</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-november-pdf/86969">Forum Discussion</a></li>
</ul>



<p><strong>How to Play:</strong></p>



<p>Each month we&#8217;ll announce a new theme and share an example project of our own. Share your projects to the Xojo Forum thread for that month via GitHub (all the links you need are posted above ↑ ). Learn how to use <a href="https://blog.xojo.com/2024/04/02/using-xojo-and-github/">Xojo and GitHub</a>.</p>



<p><strong>The Prizes:</strong></p>



<p>Monthly winners get $100 at the Xojo store. Every month you submit a project is another chance to win the grand prize. The grand prize is $250 cash plus a Xojo Pro license and a year of GraffitiSuite and will be announce in December. Learn more about the <a href="https://blog.xojo.com/2025/01/09/year-of-code-2025-kickoff/#prizes">prizes</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Microsoft Ends Support for Windows 10</title>
		<link>https://blog.xojo.com/2025/11/05/microsoft-ends-support-for-windows-10/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Wed, 05 Nov 2025 18:51:39 +0000</pubDate>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[Windows 10]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15501</guid>

					<description><![CDATA[On October 14, 2025, Windows 10 reached the end of its support from Microsoft. According to their support page: At this point technical assistance, feature&#8230;]]></description>
										<content:encoded><![CDATA[
<p>On October 14, 2025, Windows 10 reached the end of its support from Microsoft. <a href="https://support.microsoft.com/en-us/windows/windows-10-support-has-ended-on-october-14-2025-2ca8b313-1946-43d3-b55c-2b95b107f281">According to their support page</a>:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>At this point technical assistance, feature updates and security updates is no longer provided.</p>
</blockquote>



<p>Released in July 2015, Windows 10 had a good run. It was well-received and served many millions of people well. When it was introduced, Microsoft said that Windows 10 would be the &#8220;<a href="https://www.theverge.com/2015/5/7/8568473/windows-10-last-version-of-windows">last version of Windows</a>&#8220;, but given where we are now that clearly did not end up being true.</p>



<p>If your development machine is still running Windows 10, you really need to get it upgraded to Windows 11. Unfortunately, many perfectly usable computers running Windows 10 do not meet the system requirements for Windows 11, which leaves a lot of people in the lurch. If you really have to stick with Windows 10 for a while longer, Microsoft will sell you an <a href="https://www.microsoft.com/en-us/windows/extended-security-updates">Extended Security Update</a> for $30. This will extend support one more year, so out to late 2026.</p>



<p>What does this mean for Xojo? Nothing just yet. We still have Windows 10 as a supported OS, but don&#8217;t expect that to last much longer. Once an OS vendor drops support for an OS, we have to follow that guidance at some point. Expect Xojo to discontinue Windows 10 support at some point in 2026.</p>



<p><em>Paul learned to program in BASIC at age 13 and has programmed in more languages than he remembers, with Xojo being an obvious favorite. When not working on Xojo, you can find him talking about retrocomputing at <a href="https://goto10.substack.com" target="_blank" rel="noreferrer noopener">Goto 10</a> and </em>on Mastodon @lefebvre@hachyderm.io.</p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
