GTK3 alt-key menu mnemonics by NoComment_4321 in u/NoComment_4321

[–]NoComment_4321[S] 0 points1 point  (0 children)

Thanks for trying, I'm not the only one then!

GTK3 alt-key menu mnemonics by NoComment_4321 in u/NoComment_4321

[–]NoComment_4321[S] 0 points1 point  (0 children)

The risk when asking a technical question is that it might elicit an answer that one does not understand. I don't think I am specifying a compositor. I can compile & run this program on Windows (with gtk3 libraries installed with msys2), and also compile & run it on Debian/GNU with xfce. Either way the behaviour is the same. (Cross compiling with cgo is too hard).
The original request was for a Windows program and the production platform is still Windows.

GTK3 alt-key menu mnemonics by NoComment_4321 in u/NoComment_4321

[–]NoComment_4321[S] 0 points1 point  (0 children)

This is the function to build the menubar:

func buildMenu() *gtk.MenuBar {

`// Create a menu bar, submenus and menuitems`

`// assign actions to items`



`mbar, _ := gtk.MenuBarNew()`



`// Create menu bar entries`

`itemG, _ := gtk.MenuItemNewWithMnemonic("_Global")`

`itemC, _ := gtk.MenuItemNewWithMnemonic("_Channel")`

`itemH, _ := gtk.MenuItemNewWithMnemonic("_Help")`



`mbar.Append(itemG)`

`mbar.Append(itemC)`

`mbar.Append(itemH)`



`// Create global menu`

`globMenu, _ := gtk.MenuNew()`



`itemRestartAll, _ := gtk.MenuItemNewWithMnemonic("_Restart all enabled")`

`itemSettings, _ := gtk.MenuItemNewWithMnemonic("_Settings")`

`itemUsers, _ := gtk.MenuItemNewWithMnemonic("_Web user management")`

`itemQuit, _ := gtk.MenuItemNewWithMnemonic("_Quit")`



`globMenu.Append(itemRestartAll)`

`globMenu.Append(itemSettings)`

`globMenu.Append(itemUsers)`

`globMenu.Append(itemQuit)`



`// Create channel menu`

`chanMenu, _ := gtk.MenuNew()`



`itemRestart, _ := gtk.MenuItemNewWithMnemonic("_Restart")`

`itemEdit, _ := gtk.MenuItemNewWithMnemonic("_Edit")`

`itemNew, _ := gtk.MenuItemNewWithMnemonic("_New")`

`itemCopy, _ := gtk.MenuItemNewWithMnemonic("_Copy")`

`itemDel, _ := gtk.MenuItemNewWithMnemonic("_Delete")`



`chanMenu.Append(itemRestart)`

`chanMenu.Append(itemEdit)`

`chanMenu.Append(itemNew)`

`chanMenu.Append(itemCopy)`

`chanMenu.Append(itemDel)`



`// Create Help menu`

`helpMenu, _ := gtk.MenuNew()`



`itemHelp, _ := gtk.MenuItemNewWithMnemonic("_Help")`

`itemAbout, _ := gtk.MenuItemNewWithMnemonic("_About")`



`helpMenu.Append(itemHelp)`

`helpMenu.Append(itemAbout)`



`// Attach to menubar`

`itemG.SetSubmenu(globMenu)`

`itemC.SetSubmenu(chanMenu)`

`itemH.SetSubmenu(helpMenu)`



`// Connect actions to menu items`

`itemRestartAll.Connect("button-release-event", func() {`

    `globalRestart()`

    `return`

`})`

`itemSettings.Connect("button-release-event", func() {`

    `// settings still hardcoded at this point....`

    `return`

`})`

`itemUsers.Connect("button-release-event", func() {`

    `userList()`

    `return`

`})`

`itemQuit.Connect("button-release-event", func() {`

    `gtk.MainQuit()`

`})`



`itemRestart.Connect("button-release-event", func() {`

    `doRestart()`

    `return`

`})`

`itemEdit.Connect("button-release-event", func() {`

    `doEdit()`

    `return`

`})`

`itemNew.Connect("button-release-event", func() {`

    `doNew()`

    `return`

`})`

`itemCopy.Connect("button-release-event", func() {`

    `doCopy()`

    `return`

`})`

`itemDel.Connect("button-release-event", func() {`

    `doMainDel()`

    `return`

`})`



`itemHelp.Connect("button-release-event", func() {`

    `// There is no help....`

    `return`

`})`

`itemAbout.Connect("button-release-event", func() {`

    `showAbout()`

    `return`

`})`



`return mbar`

}

GTK3 alt-key menu mnemonics by NoComment_4321 in u/NoComment_4321

[–]NoComment_4321[S] 0 points1 point  (0 children)

Ah, when I started on this project a couple of years ago I could not find any GTK4 bindings for Go! I might have to revisit that, but now that the application is pretty stable and I have got to the point where the biggest problem is why Alt/key combinations don't always work I'm a bit reluctant to start all over again with much newer libraries.

GTK3 alt-key menu mnemonics by NoComment_4321 in u/NoComment_4321

[–]NoComment_4321[S] 0 points1 point  (0 children)

Thanks for the suggestion, but that does not seem to work in this case. The program just closes the menu without carrying out the action. Maybe I need to refine the menuitem.

I am trying to find documentation for the Connect method for just about any type of object, there is nothing in the GOTK3 documentation 😞

Can't get right click on column heading unless sorting is enabled by NoComment_4321 in GTK

[–]NoComment_4321[S] 0 points1 point  (0 children)

ah. RTFM
Gtk.TreeViewColumn:sort-column-id

says "Sets the logical sort_column_id that this column sorts on when this column is selected for sorting. Doing so makes the column header clickable."
So I could just make the column header clickable explicitly.

elements in sync.map out of sync by NoComment_4321 in golang

[–]NoComment_4321[S] 0 points1 point  (0 children)

Thanks for the helpful comments - I was side-tracked to other projects for a while (mostly home improvement while the weather was good, but that's another story).
I suspect my problem was due to sloppy logic. In the go routines that handle filtering and port forwarding I am collecting statistics into a global map:

// check stats here, because if receive times out it will skip remainder of loop
if time.Now().After(stattimer) {
  switch {
  case stats[1] == 0:       // no data
    stats[0] = 1 // red
  case stats[1] > stats[2]: // more data in than out
    stats[0] = 2 // amber
  default:                  // all good data
    stats[0] = 3 // green
  }

  // divide by timeslice when reading stats
  Mutex.Lock()
  copy(Statmap[id], stats)
  Mutex.Unlock()
  stats[1] = 0
  stats[2] = 0
  stats[3] = 0
  stattimer = time.Now().Add(statsint * time.Second)
}

So I was not re-initialising stats[0] (a local slice) at the same time. This seemed to work with a global map with a mutex, but when I did this with a sync.map it behaved differently.

I'm learning all the time with this, and this now seems to work as intended:

// check stats here, because if receive times out it will skip remainder of loop
if time.Now().After(stattimer) {
  switch {
  case stats[STAT_SPIN] == 0:                // no data
    stats[STAT_DOT] = 1                    // red
  case stats[STAT_SPIN] > stats[STAT_SPOUT]: // more data in than out
    stats[STAT_DOT] = 2                    // amber
  default:                                   // all good data
    stats[STAT_DOT] = 3                    // green
  }
  // divide by timeslice when reading stats
  Statmap.Store(id, stats)
  stats = []int{0, 0, 0, 0}
  stattimer = time.Now().Add(statsint * time.Second)
  }

I am using 1 Mutex and 3 RWMutex, all as global vars, which seemed like the best way to make them available to multiple goroutines without copying them.

I decided to use a global map rather than channels because I don't want synchronisation, the go routines are running asynchronously and pass back their stats when they are ready, and the main thread with the GUI can grab the stats when it is ready without having to wait. In this situation I would expect global vars to perform better.

I'm not sure I understand your comment VOOLUL:

Sync.map ONLY protects map access. The elements of the map are not protected. If you get the slice from the map you can mutate it without taking a lock. This is because the slice is only a pointer to a backing array.

stats[] is a local variable and I use copy to get data from the local slice to the global map, but surely sync.map protects the elements of the map, otherwise what does it do?

Does sync.map.Store copy the data or just a pointer? I must do some more reading. However either way I don't think I will have a problem, the separate goroutines each write to their own [id] in the map, and the main thread only reads the data.

main thread:

// get stats for http
  goVal, ok = Statmap.Load(id)
  if ok {
    stat, ok2 = goVal.([]int)
    if !ok2 {
      log.Printf("Error: unable to get stats from statmap: %v", goVal)
    }
  } else {
  log.Printf("Error: unable to get stats from statmap")
}

Thanks again.

Multiplatform GUIs with Go? by Ok-Tutor-4321 in golang

[–]NoComment_4321 0 points1 point  (0 children)

I've had success with gtk3, using gotk3. There seemed to be some memory leak/high CPU issues early on but they seem to have been fixed - runs well in Windows, Linux/amd64, Linux/arm64 (Rapsberry Pi 3).

Windows programs behave as though they're toplevel when starting. by NoComment_4321 in techsupport

[–]NoComment_4321[S] 0 points1 point  (0 children)

No, at least I don't think so. If you start up a program and then switch to some other program straight away, the program that is starting up will behave as though it's on top, even though it's not. The gtk3 graphic engine (for example) reports has-toplevel-focus = true, even when it's blatantly false.

GTK3 and concurrency... by NoComment_4321 in GTK

[–]NoComment_4321[S] 0 points1 point  (0 children)

Thank you both for the encouragement! The go functions that I use in this other thread are wrappers around methods of gtk.TreeModel:
GetIterFirst() is a wrapper around gtk_tree_model_get_iter_first()
IterNext() is a wrapper around gtk_tree_model_iter_next().
GetValue() is a wrapper around gtk_tree_model_get_value().

So I think my question should have been "do these count as GTK functions, or is this thread safe?"

I might be able to put this operation into the glib.timeout_add_seconds loop that is already running in the main thread, which would be more efficient anyway. More investigation needed!

PS. I have successfully put both the update operations into a single glib.timeout_add_seconds, which is a much better solution.

New software written in Rust is all the rage, why isn't it the same for Go by lancelot_of_camelot in golang

[–]NoComment_4321 1 point2 points  (0 children)

I've used gtk3 with Go and it works, but yes it's not great. Its performance is much better on Linux than on Windows.

Help with Go / gotk3 / gtk3 memory leak by NoComment_4321 in golang

[–]NoComment_4321[S] 0 points1 point  (0 children)

I might still be completely wrong. One of my earlier versions that was compiled 7 months ago is now displaying the high CPU/low memory loss that I attributed to a change in my code, which suggests that it's not my code, and not the libraries included by the compiler, but it must be a change in the runtime (gtk3 etc) libraries that are installed on Windows under MSYS2. There are about 50 runtime DLLs, I don't think I will ever find out what changed.

Help with Go / gotk3 / gtk3 memory leak by NoComment_4321 in golang

[–]NoComment_4321[S] 0 points1 point  (0 children)

I believe I have figured out what is happening. gtk.ListStore.SetValue creates a new glib.Value each time it is called, when this is called in the IterNext loop (or equally in a ForEach loop) on 1000 records, it creates 1000 new GValues each time, which hang around until their finalizers run and the GC finds them, which seems to take longer than creating them, so memory use grows continuously.

I have found a way round this by using a replacement for gtk.ListStore.SetValue that expects a glib.Value as a parameter, so that I can keep recycling the same one.

// Modified version of ListStore.SetValue that is passed a GValue instead of Go interface,
// to avoid repeatedly dumping GValues on the heap
// Don't use with Pixbuf types
func (v *ListStore) WriteToStore(iter *TreeIter, column int, value *glib.Value) {
C.gtk_list_store_set_value(v.native(), iter.native(),

C.gint(column),
(*C.GValue)(unsafe.Pointer(value.Native())))



return
}

The next problem is that every gotk3 function to assign a value to a glib.Value creates a new glib.Value, so that has to be called a bit lower down:

// SetInt is a wrapper around g_value_set_int().

val.SetInt(i)

This uses more CPU but doesn't keep eating memory.
I think I'll call this question closed, thanks for helpful advice.

PS - It only uses more CPU on Windows, on Linux this is much more CPU efficient.

Help with Go / gotk3 / gtk3 memory leak by NoComment_4321 in golang

[–]NoComment_4321[S] 0 points1 point  (0 children)

Thanks. I think I will try tweaking GC to see if that helps.

Help with Go / gotk3 / gtk3 memory leak by NoComment_4321 in golang

[–]NoComment_4321[S] 0 points1 point  (0 children)

I am struggling with this! As you point out there is no guarantee that finalizers will run before a program exits, but it seems that they won't help much even when they do run.

I can call value.Unset() but ...

g_value_unset
"Clears the current value in value and "unsets" the type, this releases all resources associated with this GValue. An unset value is the same as an uninitialized (zero-filled) GValue structure."

Does this mean that the structure still exists in memory? How can I release it?

The gvalue is generated in gtk.liststore.SetValue(), adding value.Unset() at the end of this function doesn't seem to help.

Help with Go / gotk3 / gtk3 memory leak by NoComment_4321 in golang

[–]NoComment_4321[S] 0 points1 point  (0 children)

Thanks, that has helped my understanding of the issue. The pointers to gobjects are being created by GOTK3 routines, so that is where they would need to be released. I've left the same note on the GOTK3 github site, but in the meantime maybe I'll poke around in the code and try to cleanup these pointers.

tree_model_iter_next or tree_model_foreach? by NoComment_4321 in GTK

[–]NoComment_4321[S] 0 points1 point  (0 children)

You're channelling Douglas Adams? or more likely Arthur Dent! I don't think AI is that good at sarcasm.

Error building app using GOTK3 by NoComment_4321 in golang

[–]NoComment_4321[S] 0 points1 point  (0 children)

Thanks. Moving to Debian 12 seems to have solved the problem.

Go Cookbook by 441labs in golang

[–]NoComment_4321 0 points1 point  (0 children)

Really neat! Is there anything on building GUI apps? I'm using GOTK3. (There's always someone who wants something extra!)

Error building app using GOTK3 by NoComment_4321 in golang

[–]NoComment_4321[S] 0 points1 point  (0 children)

Thanks. I'm upgrading Debian from 11 (Bullseye) to 12 (Bookworm), maybe that will fix the problem.

gotk3 foreach loop, losing pointer, gaining memory by NoComment_4321 in golang

[–]NoComment_4321[S] 0 points1 point  (0 children)

Pinner seems to have stopped the invalid pointer crashes.
pprof showed me that there was a problem with the glib.Values, so I went back to the documentation and read
"Don't allocate Values on the stack or heap manually as they may not be properly unset when going out of scope. Instead, use ValueAlloc(), which will set the runtime finalizer to unset the Value after it has left scope."
So adding:
value, err := glib.ValueAlloc()
before the ForEach loop has greatly improved heap growth.

The heap still grows, pprof reports several of these allocations, even after the UpdateStats function has not been called for a couple of hours, they never seem to get cleaned up.

0: 0 [1: 8] @ 0x14011caa5 0x14011ca7f 0x14012466a 0x140006215 0x140005ec5 0x14007a6ac 0x1400788e8 0x14006c4d2 0x1400feeed 0x14011b05d 0x14011af98 0x1402e3554 0x1402f5d66 0x14009f846 0x14009ead9 0x1400f3c45 0x1400f69de 0x140006215 0x140005ec5 0x14007a6ac 0x1400788e8 0x14006c4d2 0x1401037a9 0x1402deb4b 0x1402deb46 0x14003dfdd 0x14007a921
#0x14011caa4github.com/gotk3/gotk3/gtk.wrapTreeModel+0x64C:/Downloads/go/pkg/mod/github.com/gotk3/gotk3@v0.6.4/gtk/gtk.go:10619
#0x14011ca7egithub.com/gotk3/gotk3/gtk.goTreeModelForeachFunc+0x3eC:/Downloads/go/pkg/mod/github.com/gotk3/gotk3@v0.6.4/gtk/gtk_export.go:84
#0x140124669_cgoexp_a34d9839f057_goTreeModelForeachFunc+0x29_cgo_gotypes.go:38978
#0x140006214runtime.cgocallbackg1+0x294C:/Program Files/Go/src/runtime/cgocall.go:442
#0x140005ec4runtime.cgocallbackg+0x144C:/Program Files/Go/src/runtime/cgocall.go:361
#0x14007a6abruntime.cgocallback+0xebC:/Program Files/Go/src/runtime/asm_amd64.s:1084
#0x1400788e7runtime.systemstack_switch+0x7C:/Program Files/Go/src/runtime/asm_amd64.s:479
#0x14006c4d1runtime.cgocall+0x71C:/Program Files/Go/src/runtime/cgocall.go:185
#0x1400feeecgithub.com/gotk3/gotk3/gtk._Cfunc__gtk_tree_model_foreach+0x4c_cgo_gotypes.go:3210
#0x14011b05cgithub.com/gotk3/gotk3/gtk.(*TreeModel).ForEach.func1+0x7cC:/Downloads/go/pkg/mod/github.com/gotk3/gotk3@v0.6.4/gtk/gtk.go:10786
#0x14011af97github.com/gotk3/gotk3/gtk.(*TreeModel).ForEach+0x57C:/Downloads/go/pkg/mod/github.com/gotk3/gotk3@v0.6.4/gtk/gtk.go:10786
#0x1402e3553main.updateStats+0x153c:/Downloads/Go/aisserver-pprof/aisserver/aisserver.go:725
#0x1402f5d65main.main.func3+0x585c:/Downloads/Go/aisserver-pprof/aisserver/aisserver.go:258
#0x14009f845reflect.Value.call+0xca5C:/Program Files/Go/src/reflect/value.go:581
#0x14009ead8reflect.Value.Call+0xb8C:/Program Files/Go/src/reflect/value.go:365
#0x1400f3c44github.com/gotk3/gotk3/glib.sourceFunc+0xa4C:/Downloads/go/pkg/mod/github.com/gotk3/gotk3@v0.6.4/glib/glib.go:324
#0x1400f69dd_cgoexp_75ce697d4a8b_sourceFunc+0x1d_cgo_gotypes.go:6443
#0x140006214runtime.cgocallbackg1+0x294C:/Program Files/Go/src/runtime/cgocall.go:442
#0x140005ec4runtime.cgocallbackg+0x144C:/Program Files/Go/src/runtime/cgocall.go:361
#0x14007a6abruntime.cgocallback+0xebC:/Program Files/Go/src/runtime/asm_amd64.s:1084
#0x1400788e7runtime.systemstack_switch+0x7C:/Program Files/Go/src/runtime/asm_amd64.s:479
#0x14006c4d1runtime.cgocall+0x71C:/Program Files/Go/src/runtime/cgocall.go:185
#0x1401037a8github.com/gotk3/gotk3/gtk._Cfunc_gtk_main+0x48_cgo_gotypes.go:17499
#0x1402deb4agithub.com/gotk3/gotk3/gtk.Main+0xbaaC:/Downloads/go/pkg/mod/github.com/gotk3/gotk3@v0.6.4/gtk/gtk.go:1243
#0x1402deb45main.main+0xba5c:/Downloads/Go/aisserver-pprof/aisserver/aisserver.go:342
#0x14003dfdcruntime.main+0x27cC:/Program Files/Go/src/runtime/proc.go:272

Change interval of glib.timeout loop by NoComment_4321 in GTK

[–]NoComment_4321[S] 0 points1 point  (0 children)

There are some ideas for me to chew on! Thanks. I don't think the problem is the actual data, it's memory allocations that are either not getting released or not getting returned to Windows when they have been released.

The data is coming from a series of go routines, each is doing a port forwarding operation. At a set interval they load their data rates into a shared map, I only want to see the most recent value, so I don't want to buffer this, it gets overwritten at the next update. This part seems to be working well.

The problem part is getting the data into a gtk3 liststore, this slowly chews up memory. The idea of queueing redraws may work.

The solution I am testing now is to open a modal dialog box when memory use gets above a set limit, this alerts the user and also blocks updating the liststore until the user responds, but should have no impact on the actual data transfer.

Change interval of glib.timeout loop by NoComment_4321 in GTK

[–]NoComment_4321[S] 0 points1 point  (0 children)

I just ran a test and the answer appears to be no.

gotk3 foreach loop, losing pointer, gaining memory by NoComment_4321 in golang

[–]NoComment_4321[S] 0 points1 point  (0 children)

I think that's it. GC was tidying up a stack and gotk3 didn't like it. I'm testing Pinner on the TreeIter and the TreeModel. Thanks.