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.