GTK+ 4 suggestions

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

GTK+ 4 suggestions

Gtk+ - General mailing list

I'm new here, and here to cause some trouble. I just wrote my first GTK+3 app - or rather, I adapted an existing C++ program to give it a GUI with GTK+3, and the distinction is important for reasons I'll make clear. It wasn't a fun experience, and I'll try to keep ranting to a minimum, but I'm here to ask people to seriously and thoughtfully consider that gtk+4 embrace some new ideas.

1. Threads are here to stay
A number of years ago I was doing something in python and tkinter, and got a crash out of tkinter. I dug a bit and realized I'd found a tkinter issue, and there wasn't a workaround. Since I was stuck - and annoyed - I wrote my own GUI toolkit, specific to Windows (but using openGL) and python. Frankly it looked like crap, but it had the feature of features I'd always dreamed of - thread safety. Complete thread safety, invisible to the coder. You could delete a widget from any thread at any time, including from the click callback of the widget itself, and it sorted everything out for you. No explicit locking, no hangs or crashes.

I can't tell you how freeing this was or how much I've missed it since. Widgets are just resources and should be like any other resource. Think of files on linux. If one thread is writing to a file and another decides to delete the file, well, maybe you got what you wanted or maybe you didn't, but the operating system does not refuse your request, hang or crash. The file is your resource, and as such, you do what you want with it, from any thread at any time. The resource manager, in this case the OS, deals with it all, leaving you free to Just Code(tm).

My C++ application is now riddled with gdk_threads_add_idle calls. It has to be. It has a lot of threads, each doing independent tasks with sockets and things, and sometimes they want to update a label with new text or new colors. And instead of calling GTK and saying "do this", I now have a bunch of functions that have to get injected into GTK, each returning false. Now the code is ugly. And I'm not going to redesign it around some central GTK world view; the fact that it paints a screen with status is not the main point of the application and GTK shouldn't demand a starring role.

Abolish the concept of a main gtk thread. "Anything anywhere and real soon now" should be the motto.


2. My pixels, not yours. Hands off.
I know that Gtk has huge investment in flowing, springy, widget layout. Yay adaptability to new screen sizes. But sometimes, you know, I just want a widget to stay where I put it.

Sure, if you're writing an app that has to adapt to a 2x3" phone's screen or a 20x8' foot, twenty billion pixel wall screen, having the GUI engine manage sizing is nice. And monitors keep getting bigger, so...

Except wait. They don't anymore. These days, there's small screens, desktop screens, and massive wall displays, and applications rarely cross from one to the other. When they do, they're already coded to adapt, because layout is philosophically different for a phone and a huge screen, and different in ways that the GUI engine isn't likely to be smart about without help.

In other words there's a place in the world for the ability to Visual-Basic-Style-I-said-This-Big-And-Right-Here-and-no-backtalk-out-of-you nailing down of widgets, for specific niche applications. Maybe Glade can do this, but every time I Googled, I found threads saying "that's not the Gtk way".

One True Wayism can have merits, but not in GUIs. Make a GTK API that makes it easy to draw exactly what I want. My application is a fixed display on a wall, and I'm not happy to see fields shifting around because the very large Current Time field ticked over to skinnier numbers. (I'm sure this is fixable using the current toolkit - but apparently not trivially.)


3. I have to do what? Just to control colors and text in labels?
Maybe I did this wrong, but my goal was a black background, and then a bunch of labels of various sizes. I need to be able to update the text color and background color of the labels on the fly; everything from slow adjustment of text color to indicate changing states, to ohMyGoshAProblem! flashing labels at 4/sec because something's badly wrong. Simple, no?

Simple not. It took a few days and I still didn't get exactly what I wanted.

First of all, I learned the hard way that if you specify a widget's background color in Glade, nothing you do at runtime can change it. (That's probably overstated, but none of the existing or depreciated calls I tried did anything.) That's just a weird bug or documentation failure, but the upshot is that it's critical to specify as little as possible in Glade and do as much as possible in code. That's simply weird. And since Glade isn't making it easy to get the layout I wanted anyway, why did I bother with it?

Second, in other to get a black background everywhere, I had to use css. Not a lot of it: *{background-color: black;} got it done. But then there was learning curve with providers and those are tricker than they should be; it was a great moment when the window finally turned black. It should have taken ten seconds boring seconds in Glade. Why did I need a css file? What is this stuff about providers and screens?

And then there's coloring the text itself. In the end I generated markup strings on the fly: <span yadda yadda>My carefully escaped text because & happens</span>. They worked (once I cleared all the attributes out of Glade). But why am I generating instructions in a clumsy markup language, to be grokked by some underlying interpreter (that can only run in a thread that's not me)? I'm on a raspberry pi - I'd rather not use cycles for unnecessary parsing. You used to have override functions for this stuff. Simple, clear, here's the color I want and I don't have to generate a goofy string to get it. Why on earth are they depreciated? 

And I still haven't gotten the entire label to change to the background color I want - just the background of the text itself, which doesn't always fill the label. Good enough for now I guess. 


So here's the upshot.

Simple things should be simple; setting colors of anything should be trivial. Sometimes the programmer needs to be in control of all the aspects of everything. CSS and markup languages are great and all, and if you're coding apps that need to play in a user-tweakable thematic playpen and be easy for non-programmers to customize, they're great. But not everything does or should work that way. Gtk+ 3 makes it hard to do it any other way.

I realize this may be contentious. But while I'm not fundamentally a GUI designer, I've been writing applications for decades and have a pretty good idea what happens inside GUI engines. I've used commercial ones (Visual Basic, Java), written a couple, messed around with openGL. I know what I need to get things done, and I've come to the conclusion that packages like Gtk are designed around the convenience of the library coder (make the user bring all his work to MY thread, muhahaha). I think it's time for that to change, so I propose the change starts with Gtk+4. Bring back simplicity and control and give me true thread safety or give me, alright, not death, but maybe a sympathetic implementation.


_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list
Reply | Threaded
Open this post in threaded view
|

Re: GTK+ 4 suggestions

Chris Moller-3

All of which is why I'm slowly abandoning GTK for Qt.  GTK has been turned into an inflexible bureaucratic nightmare.  I can either spend my time trying to figure out how to outwit the limitations GTK has been saddled with, or I can spend my time learning a new toolkit.  The latter is far more productive.


On 22/07/18 13:26, scott via gtk-list wrote:

I'm new here, and here to cause some trouble. I just wrote my first GTK+3 app - or rather, I adapted an existing C++ program to give it a GUI with GTK+3, and the distinction is important for reasons I'll make clear. It wasn't a fun experience, and I'll try to keep ranting to a minimum, but I'm here to ask people to seriously and thoughtfully consider that gtk+4 embrace some new ideas.

1. Threads are here to stay
A number of years ago I was doing something in python and tkinter, and got a crash out of tkinter. I dug a bit and realized I'd found a tkinter issue, and there wasn't a workaround. Since I was stuck - and annoyed - I wrote my own GUI toolkit, specific to Windows (but using openGL) and python. Frankly it looked like crap, but it had the feature of features I'd always dreamed of - thread safety. Complete thread safety, invisible to the coder. You could delete a widget from any thread at any time, including from the click callback of the widget itself, and it sorted everything out for you. No explicit locking, no hangs or crashes.

I can't tell you how freeing this was or how much I've missed it since. Widgets are just resources and should be like any other resource. Think of files on linux. If one thread is writing to a file and another decides to delete the file, well, maybe you got what you wanted or maybe you didn't, but the operating system does not refuse your request, hang or crash. The file is your resource, and as such, you do what you want with it, from any thread at any time. The resource manager, in this case the OS, deals with it all, leaving you free to Just Code(tm).

My C++ application is now riddled with gdk_threads_add_idle calls. It has to be. It has a lot of threads, each doing independent tasks with sockets and things, and sometimes they want to update a label with new text or new colors. And instead of calling GTK and saying "do this", I now have a bunch of functions that have to get injected into GTK, each returning false. Now the code is ugly. And I'm not going to redesign it around some central GTK world view; the fact that it paints a screen with status is not the main point of the application and GTK shouldn't demand a starring role.

Abolish the concept of a main gtk thread. "Anything anywhere and real soon now" should be the motto.


2. My pixels, not yours. Hands off.
I know that Gtk has huge investment in flowing, springy, widget layout. Yay adaptability to new screen sizes. But sometimes, you know, I just want a widget to stay where I put it.

Sure, if you're writing an app that has to adapt to a 2x3" phone's screen or a 20x8' foot, twenty billion pixel wall screen, having the GUI engine manage sizing is nice. And monitors keep getting bigger, so...

Except wait. They don't anymore. These days, there's small screens, desktop screens, and massive wall displays, and applications rarely cross from one to the other. When they do, they're already coded to adapt, because layout is philosophically different for a phone and a huge screen, and different in ways that the GUI engine isn't likely to be smart about without help.

In other words there's a place in the world for the ability to Visual-Basic-Style-I-said-This-Big-And-Right-Here-and-no-backtalk-out-of-you nailing down of widgets, for specific niche applications. Maybe Glade can do this, but every time I Googled, I found threads saying "that's not the Gtk way".

One True Wayism can have merits, but not in GUIs. Make a GTK API that makes it easy to draw exactly what I want. My application is a fixed display on a wall, and I'm not happy to see fields shifting around because the very large Current Time field ticked over to skinnier numbers. (I'm sure this is fixable using the current toolkit - but apparently not trivially.)


3. I have to do what? Just to control colors and text in labels?
Maybe I did this wrong, but my goal was a black background, and then a bunch of labels of various sizes. I need to be able to update the text color and background color of the labels on the fly; everything from slow adjustment of text color to indicate changing states, to ohMyGoshAProblem! flashing labels at 4/sec because something's badly wrong. Simple, no?

Simple not. It took a few days and I still didn't get exactly what I wanted.

First of all, I learned the hard way that if you specify a widget's background color in Glade, nothing you do at runtime can change it. (That's probably overstated, but none of the existing or depreciated calls I tried did anything.) That's just a weird bug or documentation failure, but the upshot is that it's critical to specify as little as possible in Glade and do as much as possible in code. That's simply weird. And since Glade isn't making it easy to get the layout I wanted anyway, why did I bother with it?

Second, in other to get a black background everywhere, I had to use css. Not a lot of it: *{background-color: black;} got it done. But then there was learning curve with providers and those are tricker than they should be; it was a great moment when the window finally turned black. It should have taken ten seconds boring seconds in Glade. Why did I need a css file? What is this stuff about providers and screens?

And then there's coloring the text itself. In the end I generated markup strings on the fly: <span yadda yadda>My carefully escaped text because & happens</span>. They worked (once I cleared all the attributes out of Glade). But why am I generating instructions in a clumsy markup language, to be grokked by some underlying interpreter (that can only run in a thread that's not me)? I'm on a raspberry pi - I'd rather not use cycles for unnecessary parsing. You used to have override functions for this stuff. Simple, clear, here's the color I want and I don't have to generate a goofy string to get it. Why on earth are they depreciated? 

And I still haven't gotten the entire label to change to the background color I want - just the background of the text itself, which doesn't always fill the label. Good enough for now I guess. 


So here's the upshot.

Simple things should be simple; setting colors of anything should be trivial. Sometimes the programmer needs to be in control of all the aspects of everything. CSS and markup languages are great and all, and if you're coding apps that need to play in a user-tweakable thematic playpen and be easy for non-programmers to customize, they're great. But not everything does or should work that way. Gtk+ 3 makes it hard to do it any other way.

I realize this may be contentious. But while I'm not fundamentally a GUI designer, I've been writing applications for decades and have a pretty good idea what happens inside GUI engines. I've used commercial ones (Visual Basic, Java), written a couple, messed around with openGL. I know what I need to get things done, and I've come to the conclusion that packages like Gtk are designed around the convenience of the library coder (make the user bring all his work to MY thread, muhahaha). I think it's time for that to change, so I propose the change starts with Gtk+4. Bring back simplicity and control and give me true thread safety or give me, alright, not death, but maybe a sympathetic implementation.



_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list


_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list
Reply | Threaded
Open this post in threaded view
|

Re: GTK+ 4 suggestions

Paul Davis
In reply to this post by Gtk+ - General mailing list


On Sun, Jul 22, 2018 at 1:26 PM, scott via gtk-list <[hidden email]> wrote:

I'm new here, and here to cause some trouble. I just wrote my first GTK+3 app - or rather, I adapted an existing C++ program to give it a GUI with GTK+3, and the distinction is important for reasons I'll make clear. It wasn't a fun experience, and I'll try to keep ranting to a minimum, but I'm here to ask people to seriously and thoughtfully consider that gtk+4 embrace some new ideas.

1. Threads are here to stay
A number of years ago I was doing something in python and tkinter, and got a crash out of tkinter. I dug a bit and realized I'd found a tkinter issue, and there wasn't a workaround. Since I was stuck - and annoyed - I wrote my own GUI toolkit, specific to Windows (but using openGL) and python. Frankly it looked like crap, but it had the feature of features I'd always dreamed of - thread safety. Complete thread safety, invisible to the coder. You could delete a widget from any thread at any time, including from the click callback of the widget itself, and it sorted everything out for you. No explicit locking, no hangs or crashes.

I can't tell you how freeing this was or how much I've missed it since. Widgets are just resources and should be like any other resource. Think of files on linux. If one thread is writing to a file and another decides to delete the file, well, maybe you got what you wanted or maybe you didn't, but the operating system does not refuse your request, hang or crash. The file is your resource, and as such, you do what you want with it, from any thread at any time. The resource manager, in this case the OS, deals with it all, leaving you free to Just Code(tm).

My C++ application is now riddled with gdk_threads_add_idle calls. It has to be. It has a lot of threads, each doing independent tasks with sockets and things, and sometimes they want to update a label with new text or new colors. And instead of calling GTK and saying "do this", I now have a bunch of functions that have to get injected into GTK, each returning false. Now the code is ugly. And I'm not going to redesign it around some central GTK world view; the fact that it paints a screen with status is not the main point of the application and GTK shouldn't demand a starring role.

Abolish the concept of a main gtk thread. "Anything anywhere and real soon now" should be the motto.


​this is a terrible, terrible idea.

the benefits of a single-threaded GUI are huge. it makes reasoning about stuff that happens in the View (and Controller) components of the application vastly simpler.

​"It has a lot of threads, each doing independent tasks with sockets and things, and sometimes they want to update a label with new text or new colors"  .... this is just a sign of not using proper MVC design.  stuff driven by the socket should change the model; the view should always update in response to changes in the model. if you design things correctly, this just happens.

Now, if you just want a wrapper around idle_add() functions, so that they become "invisible to the coder", fine. We have code in Ardour that looks like sigc++ signals, but are actually cross thread:

     some_signal.connect (boost::bind (&SomeObject::some_method, an_object), ...., ui_thread()); // when "some_signal" happens, call SomeObject::some_method in the GUI thread

this doesn't use idle_add() either (it uses a FIFO that is used as a source for the main event loop). This sort of design is actually very nice, but I don't regard it as the job of my GUI toolkit to offer this, because in fact I need cross-thread callbacks between any of the dozens (or even hundreds) of threads inside my application.


2. My pixels, not yours. Hands off.
I know that Gtk has huge investment in flowing, springy, widget layout. Yay adaptability to new screen sizes. But sometimes, you know, I just want a widget to stay where I put it.

Sure, if you're writing an app that has to adapt to a 2x3" phone's screen or a 20x8' foot, twenty billion pixel wall screen, having the GUI engine manage sizing is nice. And monitors keep getting bigger, so...

Except wait. They don't anymore. These days, there's small screens, desktop screens, and massive wall displays, and applications rarely cross from one to the other. When they do, they're already coded to adapt, because layout is philosophically different for a phone and a huge screen, and different in ways that the GUI engine isn't likely to be smart about without help.

​sure, but much more common is "desktop, but with various different sized monitors, and users who prefer different sized windows and window layouts". that's where the box-packing paradigm ​wins. i don't really anyone advocating GTK for phones, and never have.
 

In other words there's a place in the world for the ability to Visual-Basic-Style-I-said-This-Big-And-Right-Here-and-no-backtalk-out-of-you nailing down of widgets, for specific niche applications. Maybe Glade can do this, but every time I Googled, I found threads saying "that's not the Gtk way".

One True Wayism can have merits, but not in GUIs. Make a GTK API that makes it easy to draw exactly what I want. My application is a fixed display on a wall, and I'm not happy to see fields shifting around because the very large Current Time field ticked over to skinnier numbers. (I'm sure this is fixable using the current toolkit - but apparently not trivially.)


3. I have to do what? Just to control colors and text in labels?
Maybe I did this wrong, but my goal was a black background, and then a bunch of labels of various sizes. I need to be able to update the text color and background color of the labels on the fly; everything from slow adjustment of text color to indicate changing states, to ohMyGoshAProblem! flashing labels at 4/sec because something's badly wrong. Simple, no?

Simple not. It took a few days and I still didn't get exactly what I wanted.

First of all, I learned the hard way that if you specify a widget's background color in Glade, nothing you do at runtime can change it. (That's probably overstated, but none of the existing or depreciated calls I tried did anything.) That's just a weird bug or documentation failure, but the upshot is that it's critical to specify as little as possible in Glade and do as much as possible in code. That's simply weird. And since Glade isn't making it easy to get the layout I wanted anyway, why did I bother with it?

Second, in other to get a black background everywhere, I had to use css. Not a lot of it: *{background-color: black;} got it done. But then there was learning curve with providers and those are tricker than they should be; it was a great moment when the window finally turned black. It should have taken ten seconds boring seconds in Glade. Why did I need a css file? What is this stuff about providers and screens?

​​

​you can't get the flexibility and portability of the CSS model without some costs (mostly just some learning). If you had used older versions of GTK (as I still do), you'd find lots and lots of reasons why CSS is incredibly desirable.​

i don't love GTK. but i think it's pretty good, and at least as good as the alternatives. i don't agree with any of your criticisms, and wouldn't want to seem them implemented. some of this is because i do not (and could not) use glade effectively.

_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list
Reply | Threaded
Open this post in threaded view
|

Re: GTK+ 4 suggestions

Gtk+ - General mailing list

On 07/22/2018 02:37 PM, Paul Davis wrote:
On Sun, Jul 22, 2018 at 1:26 PM, scott via gtk-list <[hidden email]> wrote:
Abolish the concept of a main gtk thread. "Anything anywhere and real soon now" should be the motto.

​this is a terrible, terrible idea.

the benefits of a single-threaded GUI are huge. it makes reasoning about stuff that happens in the View (and Controller) components of the application vastly simpler.

​"It has a lot of threads, each doing independent tasks with sockets and things, and sometimes they want to update a label with new text or new colors"  .... this is just a sign of not using proper MVC design.

Yes. It's not MVC. Because MVC is a way of doing things, but not the only way. MVC came about (partially) in response TO single threaded tookits. That doesn't mean it's a justification for one.

That's the point. Design patterns are approach, but there's advantage to having more than one aprpoach available. And in Gtk+3, there seems to have been a march towards this One True Approach.

As an example, my application takes no inputs. You don't click on it. You look at it. Originally it wasn't a GUI at all; it was an invisible service. But letting it paint a screen with current status was deemed useful, so I bolted a GUI on the side. Where, in this case, it belongs.

All I can tell you is, in the one case I had the freedom to write with a thread safe toolkit, everything became simple. Granted I wasn't writing a text editor. But there's design cost and effort in designing everything around some central graphics thread, and seeing as Gtk took two passes at supporting threading, it's clear there's some pain in deciding how to support it. My contention is that it's simply in the wrong place, and has been since the early days of the inherently single-threaded Windows message loop.

If everything was thread safe, you can still do MVC. And often you should. There's just not a gun pointing at your head telling you you must and will.
  

In other words there's a place in the world for the ability to Visual-Basic-Style-I-said-This-Big-And-Right-Here-and-no-backtalk-out-of-you nailing down of widgets,...

Will investigate, thanks.

​you can't get the flexibility and portability of the CSS model without some costs (mostly just some learning). If you had used older versions of GTK (as I still do), you'd find lots and lots of reasons why CSS is incredibly desirable.​

I'm sure it rocks, but I didn't need it or want it. It was forced on the app because I couldn't find another way. And if you need the all the infrastructure of css just to turn a window black, something is wrong.

i don't love GTK. but i think it's pretty good, and at least as good as the alternatives. i don't agree with any of your criticisms, and wouldn't want to seem them implemented. some of this is because i do not (and could not) use glade effectively.

I think that's telling. If Glade isn't effective, that says something about GTK right there. But I don't think implementing my suggestions requires obsoleting the existing interface. Continue to pump your functions into the idle loop if you want to; you just wouldn't have to.


_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list
Reply | Threaded
Open this post in threaded view
|

Re: GTK+ 4 suggestions

Paul Davis


On Sun, Jul 22, 2018 at 11:58 PM, scott via gtk-list <[hidden email]> wrote:


As an example, my application takes no inputs. You don't click on it. You look at it. Originally it wasn't a GUI at all; it was an invisible service. But letting it paint a screen with current status was deemed useful, so I bolted a GUI on the side. Where, in this case, it belongs.

​all you need to do is to take those sockets, turn them into sources that are handled inside the GUI event loop, and there's no threading anymore

now, should the communication taking place over the sockets have some time constraints that the event-handling + drawing aspects of the GUI event loop interfere with, then sure, you need threads.

but look ... in the Unix/X Window world, the fundamental design of GUI code has always been single threaded in the sense that if you want to use multiple threads to draw, you need to explicitly take locks to make it work. in the MS world, the opposite it true: there are implicit locks around everything, and you can use threads without thinking about it too much.

my reading is that one of these models is right, and one of them is wrong. if you want to tie drawing into the underyling hardware refresh cycle, then you're faced with the ultimate reality that drawing is single threaded (there's a single current screen state that gets delivered to the video hardware on each refresh cycle, by a single thread). if you want multiple threads to possibly affect what's in that screen state, then you either have to composite multiple thread outputs when handling the refresh or you have to use locks. The first one is basically insane. The second one leaves open the question of whether the locks are explicit or implicit (buried in the API implementation).

Most Unix-y programmers tend to prefer that things with costs are left explicit. MS cultivated a different culture, where (some) things were eas(ier), but the costs were hidden.

The fundamental drawing model of GTK+ is really incompatible with multi-thread drawing. It is supposed to occur in an expose event handler ONLY, with no specification of when or why that expose event is generated (could be a hardware refresh (vblank); could be a window geometry or visibility change; could be other things. The idea that your socket-listening thread can "just draw somewhere" is at odds with this, unless you draw into an off-screen buffer of some sort. Problem is, you still need locks to use these buffers during the expose handler, and you're basically talking about compositing the result of each thread. Which is nuts.
 
i don't love GTK. but i think it's pretty good, and at least as good as the alternatives. i don't agree with any of your criticisms, and wouldn't want to seem them implemented. some of this is because i do not (and could not) use glade effectively.

I think that's telling. If Glade isn't effective, that says something about GTK right there.

​i wasn't commenting on glade's effectiveness. our development model just doesn't use RAD tools, because it's not really the right concept for how our GUI operates. it's not Glade that we don't use - we wouldn't use any similar tool on any platform.​

​finally, i don't believe that your observations about the origins of MVC are even remotely correct, but that's a sideshow.​


_______________________________________________
gtk-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtk-list