{"id":118618,"date":"2021-02-23T11:09:16","date_gmt":"2021-02-23T10:09:16","guid":{"rendered":"https:\/\/blog.jetbrains.com\/?post_type=kotlin&#038;p=118618"},"modified":"2021-12-09T11:33:14","modified_gmt":"2021-12-09T10:33:14","slug":"jetpack-compose-for-desktop-milestone-3-released","status":"publish","type":"kotlin","link":"https:\/\/blog.jetbrains.com\/zh-hans\/kotlin\/2021\/02\/jetpack-compose-for-desktop-milestone-3-released","title":{"rendered":"Compose for Desktop: Milestone 3 Released"},"content":{"rendered":"<p><strong>The Compose for Desktop journey continues<\/strong>! Since the last milestone release of Compose for Desktop, we\u2019ve done our best to bring you an even <strong>better experience<\/strong> for building fast desktop UIs with Kotlin in a modern and declarative style, based on Google&#8217;s <a href=\"https:\/\/developer.android.com\/jetpack\/compose\" target=\"_blank\" rel=\"noopener\">modern toolkit<\/a>. Today we\u2019re publishing <strong>Compose for Desktop Milestone 3<\/strong>, which introduces significant <strong>rendering and interoperability improvements<\/strong>, and makes it even easier to <strong>integrate<\/strong> and <strong>distribute<\/strong> Compose for Desktop applications.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2021\/02\/Compose3.png\" alt=\"Compose for Desktop M3 Banner\"><\/p>\n<p align=\"center\"><a class=\"jb-download-button\" href=\"https:\/\/jetbrains.com\/lp\/compose\/\" target=\"_blank\" rel=\"noopener\"><i class=\"download-icon\"><\/i>Visit the Compose for Desktop landing page<\/a><\/p>\n<p>In this post, we would like to walk you through some of the <strong>highlights of this release<\/strong>. They include:<\/p>\n<ul>\n<li><a href=\"#rendering-improvements\"><strong>Rendering improvements<\/strong><\/a>, including our newly added support for <a href=\"#directx\"><strong>DirectX<\/strong><\/a> renderers and <a href=\"#software\"><strong>software-based<\/strong><\/a> renderers, as well as new support for <a href=\"#vsync\"><strong>VSync<\/strong><\/a>.<\/li>\n<li>Improved <a href=\"#textfields\"><strong>shortcut and selection support<\/strong><\/a> for text fields<\/li>\n<li>Support for <a href=\"#svgs\"><strong>SVGs<\/strong><\/a> as an additional vector graphics format.<\/li>\n<li>The ability to <a href=\"#swing-components\"><strong>add Swing components directly<\/strong><\/a> to a composition.<\/li>\n<li>Improvements and simplifications for <a href=\"#native-distributions\"><strong>packaging, signing and notarizing<\/strong><\/a> native distributions.<\/li>\n<li>Using Compose for Desktop to <a href=\"#idea-plugins\"><strong>build plugins for IntelliJ IDEA<\/strong><\/a>.<\/li>\n<\/ul>\n<p>For further information, including a selection of bugs that we fixed in this release, have a look at the full <a href=\"https:\/\/github.com\/JetBrains\/compose-jb\/blob\/master\/CHANGELOG.md#m3\" target=\"_blank\" rel=\"noopener\">changelog<\/a>. Let\u2019s dive right in!<\/p>\n<h2>Rendering improvements<\/h2>\n<p><a name=\"rendering-improvements\"><\/a><\/p>\n<h3>DirectX support on Windows<\/h3>\n<p><a name=\"directx\"><\/a><\/p>\n<p>Via a new <strong>DirectX 12 renderer<\/strong>, Compose for Desktop now supports <strong>improved hardware-accelerated rendering<\/strong> of your applications running <strong>on Windows<\/strong>. Execution environments not supporting DirectX 12 will gracefully fall back to an OpenGL-based renderer \u2013 and, if even that fails, to an all-new software renderer also being introduced in this release.<\/p>\n<h3>Software Rendering Support<\/h3>\n<p><a name=\"software\"><\/a><\/p>\n<p>Compose for Desktop is powered by our graphics library <a href=\"https:\/\/github.com\/JetBrains\/skiko\/\" target=\"_blank\" rel=\"noopener\">Skiko<\/a>. By default, it uses an <strong>OpenGL-based renderer <\/strong>on macOS and Linux, and (now) a <strong>DirectX-based renderer <\/strong>on Windows. But not all systems on which you might want to run your application can offer such hardware acceleration. There are several reasons why <strong>hardware acceleration might not be available<\/strong>. Some examples include virtualized\/emulated machines or machines with improperly configured graphics cards or outdated drivers.<\/p>\n<p>Starting with Milestone 3, your Compose for Desktop applications will now <strong>automatically fall back to a software-based renderer<\/strong> when Skiko is not able to create a hardware-accelerated context, allowing you to run Compose for Desktop applications on <strong>virtually any hardware<\/strong>, regardless of their graphics configuration.<\/p>\n<p>For testing and benchmarking purposes, you can also explicitly force your application to use the specific renderer of your choice by setting the corresponding environment variable:  <code>SKIKO_RENDER_API=\"SOFTWARE\"<\/code> or <code>\"OPENGL\"<\/code>. However, please keep in mind that this fallback renderer is significantly slower than its hardware-accelerated counterpart (up to 4 times slower).<\/p>\n<h3>Vertical Synchronization (VSync) support<\/h3>\n<p><a name=\"vsync\"><\/a><\/p>\n<p>Milestone 3 comes with an all-new internal mechanism for synchronizing and timing its rendering process. This should help with situations where interfaces previously felt laggy due to <a href=\"https:\/\/github.com\/JetBrains\/compose-jb\/issues\/23\" target=\"_blank\" rel=\"noopener\">operating system restrictions<\/a>, or differences in synchronization between the rendering and the display refresh rate.<\/p>\n<p>This new approach for <strong>vertical synchronization (VSync)<\/strong> is an under-the-hood change, but we hope you will notice its effects! It ensures that your <strong>user interfaces remain silky smooth<\/strong> and helps your applications <strong>run consistently at the ideal frame rate<\/strong> for the monitor you\u2019re using, even on <strong>high refresh rate displays<\/strong>.<\/p>\n<h2>Text Field improvements<\/h2>\n<p><a name=\"textfields\"><\/a><\/p>\n<p>One of the most anticipated changes included with this release is a number of improvements around the behavior of the <code>TextField<\/code> component. <strong>Keyboard shortcuts<\/strong> now work with text fields in Compose for Desktop! This includes <strong>clipboard shortcuts<\/strong> (e.g. \u2318 or <code>Ctrl<\/code> + <code>C<\/code>\/<code>X<\/code>\/<code>V<\/code>), shortcuts for <strong>creating and modifying selections<\/strong> (e.g. \u2318 or <code>Ctrl<\/code> + <code>A<\/code>, <code>Shift<\/code> or <code>Ctrl-Shift<\/code> + Arrow Keys, &#8230;), and <strong>deleting text<\/strong>. Depending on the platform you\u2019re running your Compose for Desktop application on, your user will be able to use <strong>canonical shortcuts<\/strong> to modify text field content.<\/p>\n<p>Text fields now also support basic <strong>undo and redo functionality<\/strong> (via \u2318 or <code>Ctrl<\/code> + <code>Z<\/code> \/ <code>Shift-Z<\/code>), and their <strong>mouse selection behavior<\/strong> has been adjusted to support Shift-dragging to <strong>expand or shrink<\/strong> text selections.<\/p>\n<p>As text fields are an integral part of many applications, we will <a href=\"https:\/\/github.com\/JetBrains\/compose-jb\/issues\/277\" target=\"_blank\" rel=\"noopener\">continue<\/a> to improve their feature set in Compose for Desktop.<\/p>\n<h2>Support for Scalable Vector Graphics (SVG)<\/h2>\n<p><a name=\"svgs\"><\/a><\/p>\n<p>Alongside its support for Android\u2019s <a href=\"https:\/\/developer.android.com\/guide\/topics\/graphics\/vector-drawable-resources\" target=\"_blank\" rel=\"noopener\">Vector Drawables<\/a>, Compose for Desktop now provides support for <strong>vector graphics in <a href=\"https:\/\/en.wikipedia.org\/wiki\/Scalable_Vector_Graphics\" target=\"_blank\" rel=\"noopener\">SVG<\/a> format<\/strong>. By passing the result of the newly introduced <code>svgResource<\/code> function to the <code>painter<\/code> parameter of an <code>Image<\/code>, we can now draw SVG files from our <code>resources<\/code> directory into our Compose for Desktop window, as the following small example illustrates:<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">\nimport androidx.compose.desktop.Window\nimport androidx.compose.foundation.Image\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.ui.Modifier\nimport androidx.compose.ui.res.svgResource\n\nfun main() {\nWindow {\nImage(\npainter = svgResource(&quot;images\/idea-logo.svg&quot;),\ncontentDescription = &quot;IntelliJ IDEA logo&quot;,\nmodifier = Modifier.fillMaxSize()\n)\n}\n}\n<\/pre>\n<p><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2021\/02\/loading_svg_images.png\" alt=\"\"><\/p>\n<p>For additional information about how to work with <strong>images and icons<\/strong> in Compose for Desktop, check out our tutorials on <a href=\"https:\/\/github.com\/JetBrains\/compose-jb\/tree\/master\/tutorials\/Image_And_Icons_Manipulations#loading-svg-images\" target=\"_blank\" rel=\"noopener\">image and in-app icons manipulations<\/a>.<\/p>\n<h2>Embedding Swing components in Compose for Desktop compositions<\/h2>\n<p><a name=\"swing-components\"><\/a><\/p>\n<p>Milestone 3 further <strong>improves the interoperability<\/strong> between Compose-based UIs and Swing-based components. The newly added <code>SwingPanel<\/code> enables the usage of <strong>Swing components inside a composition<\/strong> rendered by Compose for Desktop. As such, it builds the counterpart to the <code>ComposePanel<\/code>, which was introduced in Milestone 2, which allows you to seamlessly add Compose UI to Swing-based containers.<\/p>\n<p>To add a Swing component to your Compose UI, create the JComponent in the <code>factory<\/code> lambda parameter of the <code>SwingPanel<\/code> widget:<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">\n\nSwingPanel(\nbackground = Color.White,\nmodifier = Modifier.size(270.dp, 90.dp),\nfactory = {\nJPanel().apply {\nsetLayout(BoxLayout(this, BoxLayout.Y_AXIS))\nadd(actionButton(&quot;1. Swing Button: decrement&quot;, dec))\nadd(actionButton(&quot;2. Swing Button: decrement&quot;, dec))\nadd(actionButton(&quot;3. Swing Button: decrement&quot;, dec))\n}\n}\n)\n\n<\/pre>\n<p>Here&#8217;s what this sample snippet would look like in the context of a Compose for Desktop user interface:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2021\/02\/swing_panel_compressed_still.gif\" data-gif-src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2021\/02\/swing_panel_compressed.gif\"><\/p>\n<p>For more detailed information and additional samples, including the full sample shown above, check out the <a href=\"https:\/\/github.com\/JetBrains\/compose-jb\/tree\/master\/tutorials\/Swing_Integration#adding-a-swing-component-to-cfd-composition-using-swingpanel\" target=\"_blank\" rel=\"noopener\">tutorial for integration between Compose for Desktop and Swing applications<\/a> in the Compose for Desktop repository.<\/p>\n<h2>Native Distribution improvements<\/h2>\n<p><a name=\"native-distributions\"><\/a><\/p>\n<p>Compose for Desktop offers the ability to create <strong>standalone application bundles<\/strong> from your applications via <a href=\"https:\/\/github.com\/JetBrains\/compose-jb\/tree\/master\/tutorials\/Native_distributions_and_local_execution\" target=\"_blank\" rel=\"noopener\">native distributions<\/a>. The resulting artifacts are <strong>fully-self contained binaries<\/strong>, meaning that you can ship and run your applications even on systems that do not have a JVM \/ Java Runtime Environment installed. These bundles are packaged using each platform\u2019s preferred formats (<code>.dmg<\/code> \/ <code>.pkg<\/code> for macOS, <code>.deb<\/code> \/ <code>.rpm<\/code> for Linux, and <code>.msi<\/code> or <code>.exe<\/code> for Windows) and <strong>contain everything you need<\/strong> to run your Compose for Desktop application.<\/p>\n<p>With Compose for Desktop M3, we\u2019re adding <strong>additional improvements<\/strong> to the creation of these standalone bundles, <strong>specifically for macOS<\/strong>.<\/p>\n<h3>Signing and Notarization for macOS applications<\/h3>\n<p>Since macOS 10.15, third-party apps are required to be <strong><a href=\"https:\/\/developer.apple.com\/documentation\/xcode\/notarizing_macos_software_before_distribution\" target=\"_blank\" rel=\"noopener\">signed and notarized<\/a><\/strong>. This is an automated examination process carried out by Apple. Applications created using Compose for Desktop are no exception: the <code>.dmg<\/code> or <code>.pkg<\/code> files generated need to pass this process.<\/p>\n<p>To make this as easy as possible, we\u2019ve added the <code>notarizeDmg<\/code> and <code>checkNotarizationStatusXX<\/code> Gradle tasks, and we\u2019ve added corresponding properties to Compose for Desktop\u2019s Gradle DSL. After initial configuration, these tasks help you <strong>automatically complete the signing and notarization steps<\/strong> required to distribute your application.<\/p>\n<p>To learn about the whole process of signing and notarizing your Compose for Desktop applications for macOS, <a href=\"https:\/\/github.com\/JetBrains\/compose-jb\/tree\/master\/tutorials\/Signing_and_notarization_on_macOS\" target=\"_blank\" rel=\"noopener\">check out the tutorial in the repository<\/a>.<\/p>\n<p>In tandem with this functionality, we now also ensure that the <strong>native binaries<\/strong> of <a href=\"https:\/\/github.com\/JetBrains\/skiko\" target=\"_blank\" rel=\"noopener\">Skiko<\/a> (the graphics library Compose for Desktop depends on for its rendering) <strong>are signed on macOS<\/strong> (both on x64 and ARM).<\/p>\n<h2>Compose for Desktop in IntelliJ IDEA plugins<\/h2>\n<p><a name=\"idea-plugins\"><\/a><\/p>\n<p>To show off another interesting area to apply for Compose for Desktop, we have added a <a href=\"https:\/\/github.com\/JetBrains\/compose-jb\/tree\/master\/examples\/intelliJPlugin\" target=\"_blank\" rel=\"noopener\">working example for an IntelliJ IDEA plugin using Compose for Desktop<\/a> in the repository. Feel free to explore the code on GitHub, and use it as a starting point to build the <strong>next great plugin for IntelliJ-based IDEs<\/strong>!<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2021\/02\/idea-example.png\" alt=\"\"><\/p>\n<h2>Try out Milestone 3!<\/h2>\n<p>As with the previous versions, we hope you\u2019ll <strong>give Compose for Desktop Milestone 3 a try<\/strong>! You can find up-to-date information about how to get started in the <a href=\"https:\/\/github.com\/JetBrains\/compose-jb\/tree\/master\/tutorials\/Getting_Started\" target=\"_blank\" rel=\"noopener\">Getting Started<\/a> section of the Compose for Desktop tutorials.<\/p>\n<p>If you have used previous versions of Compose for Desktop, updating to this latest version is as easy as adjusting the <code>plugins<\/code> block of your application:<\/p>\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">\nplugins {\nkotlin(&quot;jvm&quot;) version &quot;1.4.30&quot;\nid(&quot;org.jetbrains.compose&quot;) version &quot;0.3.0&quot;\n}\n\n<\/pre>\n<p>Please note that Compose for Desktop M3 requires Kotlin 1.4.30.<\/p>\n<h2>Pre-release notes<\/h2>\n<p>This is the third milestone release of Compose for Desktop, and we will continue to work hard to provide you with the best experience possible. Please keep in mind that some of the APIs provided by Compose for Desktop may still change before a stable release. We are quickly progressing toward the first stable, production-ready release, and continue to rely heavily on your feedback to help us achieve this.<\/p>\n<h2>Give feedback and join the discussion!<\/h2>\n<p>Your feedback is particularly important during Milestone releases because it allows us to fix critical issues or include additional features before the stable release. Should you encounter any problems while working with Compose for Desktop, or identify any use cases that are not yet covered by our desktop-specific APIs, <strong>please share them with us<\/strong> in the project\u2019s issue tracker.<\/p>\n<p>If you want to <strong>talk to other developers and team members<\/strong>, we also invite you to join the discussion on the <a href=\"https:\/\/surveys.jetbrains.com\/s3\/kotlin-slack-sign-up\" target=\"_blank\" rel=\"noopener\">Kotlin Slack<\/a>. In <a href=\"https:\/\/kotlinlang.slack.com\/archives\/C01D6HTPATV\" target=\"_blank\" rel=\"noopener\">#compose-desktop<\/a> you can find discussions about Compose for Desktop, and in <a href=\"https:\/\/kotlinlang.slack.com\/archives\/CJLTWPH7S\" target=\"_blank\" rel=\"noopener\">#compose<\/a> you can discuss general topics involving Compose and Jetpack Compose on Android.<\/p>\n<p>We look forward to seeing what you\u2019ll build next using Compose for Desktop!<\/p>\n","protected":false},"author":1038,"featured_media":118502,"comment_status":"closed","ping_status":"closed","template":"","categories":[89],"tags":[6481,6385],"cross-post-tag":[6256],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/kotlin\/118618"}],"collection":[{"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/kotlin"}],"about":[{"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/types\/kotlin"}],"author":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/users\/1038"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/comments?post=118618"}],"version-history":[{"count":4,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/kotlin\/118618\/revisions"}],"predecessor-version":[{"id":211656,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/kotlin\/118618\/revisions\/211656"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/media\/118502"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/media?parent=118618"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/categories?post=118618"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/tags?post=118618"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/cross-post-tag?post=118618"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}