# Scope and purpose of racket/gui

**URL:** <https://racket.discourse.group/t/scope-and-purpose-of-racket-gui/2965>\
**Category:** Questions & Answers\
**Tags:** question, gui\
**Created:** [June 14, 2024, 8:14pm UTC](https://racket.discourse.group/t/scope-and-purpose-of-racket-gui/2965 "2024-06-14T20:14:47Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![ken](https://avatars.discourse-cdn.com/v4/letter/k/cc9497/32.png) [@ken](https://racket.discourse.group/u/ken)\
**Post date:** [June 14, 2024, 8:14pm UTC](https://racket.discourse.group/t/scope-and-purpose-of-racket-gui/2965/1 "2024-06-14T20:14:47Z")

</div>

Hello,

I'm working on putting a GUI on some Racket software I wrote. I've been playing around with racket/gui (and racket/gui/easy, which seems like a much more Racket-esque approach).

What I'm finding is that racket/gui isn't quite as sophisticated as other GUI libraries I've used. Is it by design to keep r/g simple, or does it lack more sophisticated features only because nobody has yet contributed them yet? Would feature requests (and features) be welcome? Development on r/g doesn't seem to be terribly active at the moment.

Unfortunately, r/g has 3 distinct backends so even if I figure out how to make it work on one platform, I'd be much less useful on a second, and useless on the third.

There's plenty of GUI features I'd love to have, and I might even be able to contribute for one backend, but if the goal is for r/g to stay simple above all, then I'll look elsewhere for my GUI.

Thanks!

---

<div class="post-metadata">

**Author:** ![LiberalArtist](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/liberalartist/32/151_2.png) [@LiberalArtist](https://racket.discourse.group/u/LiberalArtist)\
**Post date:** [June 15, 2024, 1:46pm UTC](https://racket.discourse.group/t/scope-and-purpose-of-racket-gui/2965/2 "2024-06-15T13:46:31Z")

</div>

From my perspective, I **don't** think "the goal is for r/g to stay simple above all".

> [@ken](#):
>
> Unfortunately, r/g has 3 distinct backends so even if I figure out how to make it work on one platform, I'd be much less useful on a second, and useless on the third.
> 
> There's plenty of GUI features I'd love to have, and I might even be able to contribute for one backend

Being cross-platform definitely is an important goal for `racket/gui`.

That said, there is also room for incremental improvement. For a recent example, a way to react to switches into or out of dark mode was added in [add application-dark-mode-handler · racket/gui@9682a95 · GitHub](https://github.com/racket/gui/commit/9682a952eb5742a0065ec18195bef7f4db7b7e25), initially only on Mac OS. GTK support was added in [Update gtk to react to dark mode changes · racket/gui@223e609 · GitHub](https://github.com/racket/gui/commit/223e6099dac482762c5e00c797eadb453c9527a1) a week later, and, for Windows, [Dark Mode under Windows · Issue #197 · racket/gui · GitHub](https://github.com/racket/gui/issues/197) is still an open issue. If you can implement a feature for one platform, others may be able to fill in support for the rest. Of course, before you put in too much time on a patch, it may be worth checking with others that your approach sounds reasonable and doesn't pose any avoidable issues for other platforms.

> [@ken](#):
>
> What I'm finding is that racket/gui isn't quite as sophisticated as other GUI libraries I've used.
> 
> …
> 
> There's plenty of GUI features I'd love to have

I'm interested in examples of missing features you'd like. I've found `racket/gui` very useful for cross-platform desktop apps, though of course I have pet peeves (e.g. [Scrolling `racket/gui` panels with the mouse](https://racket.discourse.group/t/scrolling-racket-gui-panels-with-the-mouse/957)) and wishlist items.

If you aren't aware of it, [Framework: Racket GUI Application Framework](https://docs.racket-lang.org/framework/) has a lot of additional functionality implemented on top of `racket/gui`. (This manual has a lot of room for improvement!)

---

<div class="post-metadata">

**Author:** ![benknoble](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/benknoble/32/16_2.png) [@benknoble](https://racket.discourse.group/u/benknoble)\
**Post date:** [June 15, 2024, 10:48pm UTC](https://racket.discourse.group/t/scope-and-purpose-of-racket-gui/2965/3 "2024-06-15T22:48:14Z")

</div>

I agree with Philip's comments: most of the core pieces are there, and occasionally something from modern GUI style is missing. Mostly then I've gone without as I built [https://github.com/benknoble/frosthaven-manager](https://github.com/benknoble/frosthaven-manager).

Thank you, Philip, for reminding me that [https://racket.discourse.group/t/scrolling-racket-gui-panels-with-the-mouse/957/3](https://racket.discourse.group/t/scrolling-racket-gui-panels-with-the-mouse/957/3) really needs some TLC; this has probably become my number one racket/gui peeve.

My second is also the docs: as [we wrote in our paper](https://racket.discourse.group/t/funarch-2023-functional-shell-and-reusable-components-for-easy-guis/2288), racket/gui is a white-box (transparent) framework that typically requires deep understanding of its inner workings (and the racket/class library) to use. Documentation can help this: more examples that are not DrRacket-sized (and that don't come with DrRacket's specific challenges) would be a great help. The same goes for Framework.

In the meantime, if you can do what you want performantly with racket/gui/easy, I encourage you to try it—it's a black-box framework in that components are opaque. This makes it easier to learn and use. The hooks that it offers into racket/gui guts have, in addition to being extremely valuable for complex programs, tempted me to learn bits and pieces of racket/gui in more depth.

---

<div class="post-metadata">

**Author:** ![ken](https://avatars.discourse-cdn.com/v4/letter/k/cc9497/32.png) [@ken](https://racket.discourse.group/u/ken)\
**Post date:** [June 16, 2024, 12:57am UTC](https://racket.discourse.group/t/scope-and-purpose-of-racket-gui/2965/4 "2024-06-16T00:57:41Z")

</div>

Hi, LiberalArtist!

> From my perspective, I **don't** think "the goal is for r/g to stay simple above all".

Great!

> That said, there is also room for incremental improvement.

That is encouraging. I'd potentially be willing to prototype features on one platform, if other people will help out on the rest.

> I'm interested in examples of missing features you'd like.

Since you asked: 🙂

- The table/tree/list views don't seem to have any concept of a separate data model (i.e., on-demand backing data, rather than "add all data at once"), or a view model (i.e., ability to use custom controls for cell views/editors). In fact, I'm not sure they support editing at all. And are there any user-level events, e.g., being able to detect selection changes, or column moves or resizes, or being able to put right-click menus on rows and headers? (I saw some very nice tables in ActivityLog2, and dug into the source to see how they were made. They're not GUI tables. They're just pictures which happen to be mostly text, in rows/columns. Clever.)
- The only drag-n-drop support is the ability to accept a single file dropped onto an entire window.
  - You can't make your own objects draggable.
  - You can't accept drops onto a specific control or region.
  - You can't accept any type other than a (single) pathname.  
(Coincidentally, this was also the first item on the "Feature requests/issues reported on Hacker News" issue from 2018, which was in response to a remark that "If no one asks for it, we don't know what to implement next", which is totally fair! -- but in 6 years nobody has yet touched any of the 14 items which were brought up, so I don't think it was actually anyone's limiting factor.)

- The clipboard support is also lacking. For example, I don't see any way to find out what types are available. Just today, I discovered the `get-clipboard-data` function doesn't return `#f` for unknown types, as per the documentation (filed: #328) -- which itself is not a deal-breaker, but when I run into basic bugs like this (i.e., it doesn't do what the first sentence of the documentation says), I wonder if I'm the first person to ever try using this interface, and what else is missing.
- Scrolling behaves strangely (filed as #324, though I see there have been other issues filed regarding scrolling). I started looking into this, and I really don't understand how scrolling is implemented in racket/gui -- it doesn't seem to use the native scrolling functionality at all, and I can't even decipher the comment which (I think) explains why not.
- Examples of other native widgets I want to use: Spinner, Separator, Stepper, ProgressBar, media controls, calendar (date/time) picker, other button types, popovers, ...
- Is performance a feature? I ran into trouble with putting many controls on one panel (filed: #311), due to the deep invisible hierarchies that racket/gui builds behind the scenes. There are some very pretty racket/gui applications but they all appear to be mostly custom drawing, with not many native widgets. Using just native controls, I'm getting around 1fps on my new Ryzen system, which is unusable for the types of programs I want to write.

> If you aren't aware of it, [Framework: Racket GUI Application Framework](https://docs.racket-lang.org/framework/) has a lot of additional functionality implemented on top of `racket/gui`.

I did run across that, but it seems to be mostly convenience functionality on top of racket/gui, not anything wholly new that I couldn't do myself. I'm also not sure how well it plays with racket/gui/easy, which is a much nicer abstraction I really want to use. (I really only want to write GUIs if I can do it in a declarative/functional style. If my programs end up being just a long line of `(send ...)` calls, I might as well write in Python, which is designed for that style of programming, or Racket FFI to GTK, which would give me 100% access to the native toolkit.) Framework isn't bad -- it just doesn't really address any of my main issues with racket/gui.

Thanks for responding! I'm trying not to sound too old and bitter. Racket is really very nice overall.

---

<div class="post-metadata">

**Author:** ![JustinZed](https://avatars.discourse-cdn.com/v4/letter/j/8e7dd6/32.png) [@JustinZed](https://racket.discourse.group/u/JustinZed)\
**Post date:** [June 16, 2024, 1:22am UTC](https://racket.discourse.group/t/scope-and-purpose-of-racket-gui/2965/5 "2024-06-16T01:22:10Z")

</div>

> [@ken](#):
>
> The only drag-n-drop support is the ability to accept a single file dropped onto an entire window.
> 
> - You can't make your own objects draggable.
> - You can't accept drops onto a specific control or region.
> - You can't accept any type other than a (single) pathname.  
> (Coincidentally, this was also the first item on the "Feature requests/issues reported on Hacker News" issue from 2018, which was in response to a remark that "If no one asks for it, we don't know what to implement next", which is totally fair! -- but in 6 years nobody has yet touched any of the 14 items which were brought up, so I don't think it was actually anyone's limiting factor.)

I wrote a document that shows one way of implementing drag-and-drop using the Racket GUI. You might find it useful. It is at [GitHub - zamora/literate-drag-and-drop: Literate Drag and Drop Using the Racket GUI](https://github.com/zamora/literate-drag-and-drop)

---

<div class="post-metadata">

**Author:** ![ken](https://avatars.discourse-cdn.com/v4/letter/k/cc9497/32.png) [@ken](https://racket.discourse.group/u/ken)\
**Post date:** [June 16, 2024, 1:38am UTC](https://racket.discourse.group/t/scope-and-purpose-of-racket-gui/2965/6 "2024-06-16T01:38:21Z")

</div>

> In the meantime, if you can do what you want performantly with racket/gui/easy, I encourage you to try it

Oh, I have -- 1/7 of its open bug reports is mine! Not only do I think that racket/gui/easy is the most reasonable way to write GUIs in Racket, but I think the "easy" label is wrong. It might be easier, but it'd be more accurate to say it's just a better abstraction.

(In the same vein, it's also "easier" to have bignums, perhaps, but I don't have to import a special "integer/easy" to use them, and we usually just call them "integers".)

I assume that racket/gui is object-oriented (unlike every other Racket library) simply because it started out as a thin wrapper over a foreign object-oriented library. If I had a magic wand, I'd rename "racket/gui" to "racket/gui/lowlevel", and "racket/gui/easy" to "racket/gui".

I'm not sure what you mean by "performantly", though. I've not run into any cases where racket/gui/easy has any detectable performance hit. It's the racket/gui layer which gives me performance issues.

---

<div class="post-metadata">

**Author:** ![robby](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/robby/32/7_2.png) [@robby](https://racket.discourse.group/u/robby)\
**Post date:** [June 16, 2024, 1:53am UTC](https://racket.discourse.group/t/scope-and-purpose-of-racket-gui/2965/7 "2024-06-16T01:53:49Z")

</div>

Thanks for your interest and the potential of improving things! There's no question that there is more to do and having more folks interested in putting time into is just wondeful.

As for what would be desired and how to think about organizing the code, beyond what's already been said, I'd say that `racket/gui` has worked out to be something that collects functionality that is mostly bringing a common API to the different GUIs as a low-level tool to build platform-independent APIs on top of. Of course, this isn't such a well-defined thing and we've missed the mark in various ways over the years, but that seems to be the best way to think about things going forward. The framework is then one attempt to build higher-level facilities on top of `racket/gui` that are platform independent (this also is best though of as an "in spirit" guideline too, as it turned out). It's definitely the case that the framework isn't the easiest thing to use, but that guideline is what we've used to decide where to put any new functionality. So, in your list, I'd say that the table/tree/list views that have more sophisticated data/view models would be in racket/gui if their actual implementations were platform-specific (and, probably, looked different to get a platform-native feel) but probably belong in a library on top if not (and the framework would welcome that, for sure! but I understand if folks would prefer to put it elsewhere). The drag-n-drop support, however, definitely needs low-level APIs and some thought to make a racket-level interface that works well (enough) on all platforms, so it seems at least some part of that belongs in `racket/gui`. Ditto for the clipboard.

I would say that improving the performance would be awesome. For deep invisible hierarchies, we have some support (c.f., panel vs pane) but I'm sure there is more improvement that can be done.

---

<div class="post-metadata">

**Author:** ![bogdan](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/bogdan/32/8_2.png) [@bogdan](https://racket.discourse.group/u/bogdan)\
**Post date:** [June 16, 2024, 11:40am UTC](https://racket.discourse.group/t/scope-and-purpose-of-racket-gui/2965/8 "2024-06-16T11:40:45Z")

</div>

I've experimented on-and-off with extending `racket/gui` with extra controls from the "outside", for apps that don't need cross-platform support. It's possible, if you're willing to rely on some of `racket/gui`'s internals, though [somewhat more painful than working on regular Racket code](https://github.com/greghendershott/racket-mode/issues/602). The code is [here](https://github.com/Bogdanp/racket-gui-extra/tree/master) and it includes the beginnings of an outline view with a separate data model (for macOS), so maybe check that out for inspiration if that's an approach you'd be interested in. I may return to that project at some point, but, for now, I've settled on writing my GUIs using the platform toolkit (since I mostly care about macOS and iOS) and [embedding Racket](https://github.com/Bogdanp/Noise) to handle the business logic.

---

<div class="post-metadata">

**Author:** ![benknoble](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/benknoble/32/16_2.png) [@benknoble](https://racket.discourse.group/u/benknoble)\
**Post date:** [June 16, 2024, 11:53am UTC](https://racket.discourse.group/t/scope-and-purpose-of-racket-gui/2965/9 "2024-06-16T11:53:15Z")

</div>

> performantly

My application starts to experience some problems with a lot of data on the screen after a while; I wonder if it’s due to the nested container problem you mention? (I’m also running a web-server that maintains a few long-running connections with it, though, and that could be part of the problem.)

Anyway, I just checked in and am glad to see continued community interest in and development of gui-easy. I really need to extract my helpers as a package 🙂

---

<div class="post-metadata">

**Author:** ![soegaard](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/soegaard/32/19_2.png) [@soegaard](https://racket.discourse.group/u/soegaard)\
**Post date:** [June 16, 2024, 11:54am UTC](https://racket.discourse.group/t/scope-and-purpose-of-racket-gui/2965/10 "2024-06-16T11:54:09Z")

</div>

In an ideal world, there would be support for more platform-dependent GUI elements.  
It is however a difficult to task to keep up with 3 platforms at once.  
It's more realistic to what Bogdan experimented with: adding elements ad hoc when needed.

However, it is not simple to do - and I think a tutorial or elaborate example of how to add GUI elements would help. It's not easy to write though. In the case macOS it requires knowledge of: Appl'es developer documentaiton, Objective C, the FFI and the conventions used in racket/gui.

---

<div class="post-metadata">

**Author:** ![soegaard](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/soegaard/32/19_2.png) [@soegaard](https://racket.discourse.group/u/soegaard)\
**Post date:** [June 16, 2024, 11:56am UTC](https://racket.discourse.group/t/scope-and-purpose-of-racket-gui/2965/11 "2024-06-16T11:56:44Z")

</div>

I am not 100% what kind of drag-and-drop you are after, but in some case it is possible to use a pasteboard. Alex has a very nice explanation in his blog:

> **[Chess Game Using Racket's Pasteboard](https://alex-hhh.github.io/2018/10/chess-game-using-racket-s-pasteboard.html)**
>
> The Racket GUI library provides an "editor toolkit" which can be used to implement programs that use an interactive graphical canvas where objects can be moved around with the mouse. This toolkit has good reference documentation, however this...

---

<div class="post-metadata">

**Author:** ![ken](https://avatars.discourse-cdn.com/v4/letter/k/cc9497/32.png) [@ken](https://racket.discourse.group/u/ken)\
**Post date:** [June 16, 2024, 12:26pm UTC](https://racket.discourse.group/t/scope-and-purpose-of-racket-gui/2965/12 "2024-06-16T12:26:03Z")

</div>

> for now, I've settled on writing my GUIs using the platform toolkit (since I mostly care about macOS and iOS) and [embedding Racket](https://github.com/Bogdanp/Noise) to handle the business logic.

Yep, this can be a feasible approach. I think the main reason I'm not doing that myself right now is simply because both of my main projects are still in the "research/experimental" phase, and it's hard to split up a program when you don't even know what it's going to do yet.

> the beginnings of an outline view with a separate data model (for macOS)

I've used the outline view on macOS, and it's pretty good. I think it includes all of the features that I'd want, so this could be a great starting point for a cross-platform Racket interface.

---

<div class="post-metadata">

**Author:** ![ken](https://avatars.discourse-cdn.com/v4/letter/k/cc9497/32.png) [@ken](https://racket.discourse.group/u/ken)\
**Post date:** [June 16, 2024, 12:29pm UTC](https://racket.discourse.group/t/scope-and-purpose-of-racket-gui/2965/13 "2024-06-16T12:29:47Z")

</div>

The performance issues I see with racket/gui appear right away, not gradually, so my suspicion is that this is something different.

An easy way to check is starting your program with `GTK_DEBUG=interactive` and seeing if the widget hierarchy looks similar to your Racket program. If it's got 10 extra layers of `GtkFixed` and `GtkEventBox`, you may be seeing the same issue that I am.

---

<div class="post-metadata">

**Author:** ![ken](https://avatars.discourse-cdn.com/v4/letter/k/cc9497/32.png) [@ken](https://racket.discourse.group/u/ken)\
**Post date:** [June 16, 2024, 12:39pm UTC](https://racket.discourse.group/t/scope-and-purpose-of-racket-gui/2965/14 "2024-06-16T12:39:48Z")

</div>

@JustinZed, @soegaard: Those look like neat programs, but they both look different than what I mean by "drag-n-drop". Those appear to require custom drawing on a custom Racket canvas, and can only drag those objects within that canvas.

System drag-n-drop can occur from any region (in your application), to any region (even across applications). The two endpoints negotiate the type of transfer (copy, move, link, etc) and the type of data (often by MIME-type, but by UTI on macOS). The programs get to specify what the object looks like during the drag, and what the target window looks like during a hover.

This requires OS support, and isn't wrapped by racket/gui yet, so you'd need FFI or a native library. I'm sure we could put a nice Racket interface on it, but I don't know what it might look like yet.

---

<div class="post-metadata">

**Author:** ![soegaard](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/soegaard/32/19_2.png) [@soegaard](https://racket.discourse.group/u/soegaard)\
**Post date:** [June 16, 2024, 12:55pm UTC](https://racket.discourse.group/t/scope-and-purpose-of-racket-gui/2965/15 "2024-06-16T12:55:35Z")

</div>

I need to check, but I am almost certain that kind of drag-and-drop is supported.  
If I remember correctly, you can drag-and-drop an rkt-file on DrRacket.

Later:

See the documentation for `window%` and `on-drop-file`.

[https://docs.racket-lang.org/gui/window\_\_\_.html#(meth.\_(((lib.\_mred%2Fmain..rkt).\_window~3c~25~3e).\_accept-drop-files))](https://docs.racket-lang.org/gui/window___.html#%28meth._%28%28%28lib._mred%2Fmain..rkt%29._window~3c~25~3e%29._accept-drop-files%29%29)

Later:

Oh! I see now, that doesn't address your requirements.

> The only drag-n-drop support is the ability to accept a single file dropped onto an entire window.
> 
> - You can't make your own objects draggable.
> - You can't accept drops onto a specific control or region.
> - You can't accept any type other than a (single) pathname.

---

<div class="post-metadata">

**Author:** ![benknoble](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/benknoble/32/16_2.png) [@benknoble](https://racket.discourse.group/u/benknoble)\
**Post date:** [June 16, 2024, 7:18pm UTC](https://racket.discourse.group/t/scope-and-purpose-of-racket-gui/2965/16 "2024-06-16T19:18:54Z")

</div>

> [@ken](#):
>
> starting your program with `GTK_DEBUG=interactive`

Neat tip; I’m on macOS, though. Must be something else. I’ve added some more monitor panels recently to try to find out what’s happening.

---

<div class="post-metadata">

**Author:** ![LiberalArtist](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/liberalartist/32/151_2.png) [@LiberalArtist](https://racket.discourse.group/u/LiberalArtist)\
**Post date:** [June 16, 2024, 9:25pm UTC](https://racket.discourse.group/t/scope-and-purpose-of-racket-gui/2965/17 "2024-06-16T21:25:26Z")

</div>

> [@ken](#):
>
> the "Feature requests/issues reported on Hacker News" issue from 2018

For reference: [Feature requests/issues reported on Hacker News · Issue #115 · racket/gui · GitHub](https://github.com/racket/gui/issues/115)

From quickly skimming the list, I don't think all of the items are accurate: e.g. the [editor data](https://docs.racket-lang.org/gui/editor-overview.html#%28part._editordata%29) mechanism does #3, and #7 is supported by e.g. [`frame:standard-menus-mixin`](https://docs.racket-lang.org/framework/Frame.html#%28def._%28%28lib._framework%2Fmain..rkt%29._frame~3astandard-menus-mixin%29%29) and [`application-about-handler`](https://docs.racket-lang.org/gui/Windowing_Functions.html#%28def._%28%28lib._mred%2Fmain..rkt%29._application-about-handler%29%29).

* * *

> [@ken](#):
>
> Not only do I think that racket/gui/easy is the most reasonable way to write GUIs in Racket, but I think the "easy" label is wrong. It might be easier, but it'd be more accurate to say it's just a better abstraction.

I don't actually know, but when I first saw it I assumed the `easy` suffix was following @bogdan's [`net/http-easy`](https://docs.racket-lang.org/http-easy/index.html), which similarly provides abstractions over `net/http`.

* * *

> [@ken](#):
>
> > for now, I've settled on writing my GUIs using the platform toolkit (since I mostly care about macOS and iOS) and [embedding Racket](https://github.com/Bogdanp/Noise) to handle the business logic.
> 
> Yep, this can be a feasible approach. I think the main reason I'm not doing that myself right now is simply because both of my main projects are still in the "research/experimental" phase, and it's hard to split up a program when you don't even know what it's going to do yet.

In case you aren't aware, Racket can be configured to use GTK instead of the "native" toolkit on Mac OS and Windows (though I think the GTK/Windows support is not regularly tested: I was surprised when I stumbled across it in the source). You can structure your code as a `racket/gui` program but, when needed, use the [`get-client-handle`](https://docs.racket-lang.org/gui/window___.html#%28meth._%28%28%28lib._mred%2Fmain..rkt%29._window~3c~25~3e%29._get-client-handle%29%29) method of `window<%>` to grab a `GtkWidget` pointer and drop down into GTK.

* * *

# Native Widgets & Custom Drawing

> [@ken](#):
>
> Is performance a feature? I ran into trouble with putting many controls on one panel (filed: #311), due to the deep invisible hierarchies that racket/gui builds behind the scenes. There are some very pretty racket/gui applications but they all appear to be mostly custom drawing, with not many native widgets. Using just native controls, I'm getting around 1fps on my new Ryzen system, which is unusable for the types of programs I want to write.

> [@robby](#):
>
> I would say that improving the performance would be awesome. For deep invisible hierarchies, we have some support (c.f., panel vs pane) but I'm sure there is more improvement that can be done.

(The following is a somewhat vague impression I've had: hopefully people who actually know things can chime in, either with supporting evidence or with explanations of what I'm getting wrong.)

(P.S.: This ended up being very long! I've been ruminating on some of these topics for a while, though I still think it's a bit amorphous.)

A number of platform GUI toolkits seem to have "recently"(-ish) undergone some sort of transition:

| A | B | C |
| --- | --- | --- |
| [Qt Widgets](https://doc.qt.io/qt-6.5/qtwidgets-index.html) | ⮕ | [Qt Quick](https://doc.qt.io/qt-6.5/qtquick-index.html) |
| [AppKit](https://developer.apple.com/documentation/appkit/) | ⮕ | [SwiftUI](https://developer.apple.com/documentation/swiftui) |
| [Win32](https://learn.microsoft.com/en-us/windows/win32/windows-application-ui-development) | ⮕ | [WinUI](https://learn.microsoft.com/en-us/windows/apps/winui/) \[1\] |
| [GTK 3 rendering](https://blog.gtk.org/2016/06/15/drawing-in-gtk/) | ⮕ | [GTK Scene Graph Kit](https://www.bassi.io/articles/2016/07/05/gsk-demystified-1/) (GSK) in [GTK 4](https://docs.gtk.org/gsk4/classes_hierarchy.html) |

One pattern I notice is that, in the "traditional" toolkits, widget objects are resource-intensive and do not scale well. Here's an extended fragment of an even longer old discussion:

> [Dmitry Pavlov wrote at 2014-07-09 04:50 AM](https://groups.google.com/g/racket-users/c/xiKAHjIDmt8/m/m9-SGZuUVfsJ):
> 
> > I have to do a simple spreadsheet editor and I wonder  
> > whether Racket suits my needs. The main challenge  
> > is that the spreadsheet editor should be able to edit  
> > tables as big as 1000x1000 or 10000x100 cells.
> 
> @mflatt wrote [at 2014-07-09 05:15 AM](https://groups.google.com/g/racket-users/c/xiKAHjIDmt8/m/a6PUo3j2ozAJ):
> 
> > … [I]nstances of `button%` (or generally `control<%>`) in a scrolling  
> > panel will not scale well. The `racket/gui` library is not designed for  
> > it.
> > 
> > I'm not sure how much the problem is in `racket/gui` versus the  
> > underlying toolkits. Your example program scrolls nicely for me on  
> > Windows and Mac OS X, but not Unix/Gtk, but I would not conclude from that  
> > experiment that the problem is in Gtk. The problem might be the  
> > Gtk-specific part of the implementation of `racket/gui`. Also, I  
> > wouldn't expect any of the platforms to scale to 1000x1000 buttons.  
> > When I tried 100x100 on Mac OS X, it took a couple of seconds to create  
> > all of the buttons.
> > 
> > I think you would have to use `canvas%` and draw/manage the grid and  
> > controls manually. It's possible that the classes of `embedded-gui`  
> > will be useful, if you can set up a suitable harness for snips. (I've  
> > always wanted to make a `table%` class to go along with `text%` and  
> > `pasteboard%`, but I never got around to it.)
> 
> @greghendershott wrote [at 2014-07-09 9:27 PM](https://groups.google.com/g/racket-users/c/xiKAHjIDmt8/m/2-4FEl00v9sJ):
> 
> > I don't think that a big-grid GUI application like Excel will use  
> > controls for very much in its main window. Generally it is managing  
> > all that itself.
> > 
> > It might use a _few_ plain windows, such as one for the column names  
> > on top, another for the row names on the left, and then a big one for  
> > the main grid client area. Just to make it easier to clip output.
> > 
> > If the user clicks in a button-like area, it will handle that itself.  
> > e.g. If you click somewhere in the column header, it will calculate  
> > which column, and draw that column as selected.
> > 
> > If the user clicks in a region it calculates to be a cell, it _might_  
> > create a text-edit control there for in-place editing -- but just  
> > temporarily, and destroy it when editing finishes.
> > 
> > All the logic for scrolling... managed itself.
> > 
> > At least, that's how I did Windows GUI stuff like this, 15+ years ago.  
> > Usings hundreds or thousands of windows/controls was just too much  
> > overhead to get desirable speed and space. Although the overhead might  
> > be less, now, I imagine if you want a really crisp UI it's probably  
> > much the same story.
> 
> [Neil Van Dyke wrote at 2014-07-10 6:39 PM](https://groups.google.com/g/racket-users/c/xiKAHjIDmt8/m/rTpfzb5vCb0J):
> 
> > For a million cells like that, when using any language and toolkit that  
> > I know of, I would probably implement it with a mix of manual drawing  
> > and using the occasional toolkit widgets in only small numbers at a time  
> > (only for actively editing of a single cell).
> > 
> > …
> > 
> > I think that this simple approach of a manually-drawn grid and minimal  
> > use of toolkit controls will be fast with even a million cells, without  
> > much programming difficulty.

The "new" toolkits (or new features/emphasis in existing toolkits) seem to move toward approaches reminiscent of the ["Virtual DOM"](https://en.wikipedia.org/wiki/Virtual_DOM) used by some JavaScript UI frameworks. They seem to be trying to make toolkit widgets more scalable and, at least in some cases, rendering APIs are getting closer to functional programming: for example, GTK Scene Graph Kit's [`GskRenderNode`s](https://docs.gtk.org/gsk4/class.RenderNode.html) are immutable. Some are doing more sophisticated compositing, doing more work on the GPU, or otherwise pursuing performance gains.

AIUI, `gui/easy` also takes steps in this direction through its functional shell of lightweight `view<%>` objects. But I think this would be a fruitful direction for future work, both in higher-level abstraction over `racket/gui` and in identifying platform functionality that should be supported.

That sort of leads to the second, related pattern I've noticed in the toolkit transitions, which I'd introduce with the assessment in chapter 7 of [Leif Andersen's thesis, "Adding Visual and Interactive Syntax to Textual Programs"](https://www2.ccs.neu.edu/racket/pubs/dissertation-andersen.pdf) (p. 41):

> [@](#):
>
> Unfortunately, the `racket/visr` prototype falls short of the design requirement[that "an interactive-syntax extension mechanism must use the existing GUI libraries of the chosen language as much as possible" (p. 12).] …
> 
> [The `racket/gui`] framework is not powerful enough, requiring developers to use separate implementations for their application view and interactive-syntax …
> 
> Most notably, visual syntax extensions in `racket/visr` cannot make use of the existing Racket GUI library. Instead visual syntax extensions must use a custom GUI library. This major limitation means that while `racket/visr` is useful for communicating ideas and thoughts via hybrid code, it is ultimately not usable.
> 
> This technical problem is due to a division of Racket’s GUI library. This GUI library comes in two parts: an operating-system widgets layer and a code-editor layer. Code editors can be placed into both widgets and other code editors. Widgets, in contrast, can only be placed in other widgets. The design of `racket/visr`, however, necessitates embedding widgets in code-editors.
> 
> To work around this, I created a widget library that attempts to parody the Racket widget library inside of code editors. In principle, programs written for one library can be easily ported to the other. In practice though, porting these programs from one library to the other is a significant effort. As a result, to make use of interactive-syntax extensions, programmers are forced to develop two implementations of their GUI.
> 
> An unfortunate side effect of using a custom interactive-syntax GUI framework is that this custom framework is inevitably less performant than its user-facing counterpart. This means that while developers are able to read code with that uses interactive-syntax extensions, their ability to write new code is severely limited.

In `racket/gui`—and, I think, in "traditional" toolkits (or ways of using them) more generally—a `canvas<%>`, be it a `canvas%` or an `editor-canvas%`, is basically a "leaf" from the toolkit's perspective. Outside, you have one set of relatively high-level abstractions like `message%`, `radio-box%`, and `group-box-panel%`. Inside, you have a surface for Cairo drawing (`racket/draw`): any abstractions you create over it, even ones as powerful as the `editor<%>` and and `snip%` systems provide, still look to the platform just like drawing.

The "new" toolkits seem to be trying in various ways to remove some of these weaknesses and restrictions.

One motivation is performance: as the [blog post I linked to above](https://www.bassi.io/articles/2016/07/05/gsk-demystified-1/) about the motivations for GSK put it, "we can incrementally transition from the current immediate more rendering model to a more structured tree of rendering operations that can be reordered and optimized for the target graphics layer."

More interesting to me are the possibilities for expressiveness. I think many, perhaps all, of the "new" toolkits have functionality that we could use to allow toolkit widgets to be placed inside of `canvas<%>`es (or perhaps some new `canvas<%>`-like abstraction would be needed), solving problems like those encountered by `racket/visr`. Those cross-platform GUI toolkits that mostly eschew "native" widgets face similar challenges, and some seem to have found solutions. For example, Flutter can [embed an `android.view.View`](https://docs.flutter.dev/platform-integration/android/platform-views) or an [iOS `UIView`](https://docs.flutter.dev/platform-integration/ios/platform-views), and on most platforms Qt\[2\] can wrap a "native" pointer with [`QWindow::fromWinID()`](https://doc.qt.io/qt-6.5/qwindow.html#fromWinId) and embed it in Qt&nbsp;Widgets via [`QWidget::createWindowContainer()`](https://doc.qt.io/qt-6.5/qwidget.html#createWindowContainer) or in (the latest version of) Qt&nbsp;Quick via [`WindowContainer`](https://doc-snapshots.qt.io/qt6-6.7/qml-qtquick-windowcontainer.html).

In a different way, communicating more structure to the to the platform is needed to fix [DrRacket Is Inaccessible with Screenreaders · Issue #219 · racket/drracket · GitHub](https://github.com/racket/drracket/issues/219), an especially important area for improvement (though also a challenging task to take on).

I don't have an especially concrete conclusion. I, for one, find it very helpful to hear from people like @bogdan and @ken about their experiences working with the platform toolkits directly as a way to think about what might be useful to have in `racket/gui`.

For some kinds of functionality, an alternative to finding common API for all platform backends would be to adopt some cross-platform library, analogous to the way we use Cairo for `racket/draw`. (There are also obvious downsides to this approach!) For "scene graph"-like functionality, GSK, [`QRhi`](https://doc.qt.io/qt-6/qtgui-rhiwindow-example.html) (the Qt Rendering Hardware Interface), and [Webrender](https://hacks.mozilla.org/2017/10/the-whole-web-at-maximum-fps-how-webrender-gets-rid-of-jank/) (a Rust rendering engine used by Firefox—not actually web-related itself) are all cross-platform.

Well, one concrete step would be adding support for GTK 4: I have given thought to this, but there are several other things I'd need to finish before I could work on it myself.

* * *

1. I am least clear on the details for WinUI: I haven't routinely used Windows, much less programmed on it, since the days of Visual Basic 6. One of the reasons I'm enthusiastic about `racket/gui` (and Racket's cross-platform portability more generally, e.g. [Windows path support](https://docs.racket-lang.org/reference/windowspaths.html)) is that I can write portable code that almost always "Just Works" for the Windows users I need to support. 

2. As a [KDE Plasma](https://kde.org/plasma-desktop/) user, Qt is the "native" toolkit for my platform, but Qt also brings its own widgets and rendering when used on other platforms.

---

<div class="post-metadata">

**Author:** ![JohnSnow](https://avatars.discourse-cdn.com/v4/letter/j/74df32/32.png) [@JohnSnow](https://racket.discourse.group/u/JohnSnow)\
**Post date:** [June 16, 2024, 10:18pm UTC](https://racket.discourse.group/t/scope-and-purpose-of-racket-gui/2965/18 "2024-06-16T22:18:18Z")

</div>

> Well, one concrete step would be adding support for GTK 4

There are many GTK2 bits in racket/gui.

I think they should be simply dropped first to make related GTK code easier to work with.

I don't think users even aware that you can start racket/gui or drracket with GTK2 mode.

`PLT_GTK2` should be gone.
