Migrated the GTK+ backend to the new API.
This commit is contained in:
parent
affc65a5a4
commit
385993792f
|
@ -27,8 +27,9 @@ import "C"
|
||||||
func our_window_delete_event_callback(widget *C.GtkWidget, event *C.GdkEvent, what C.gpointer) C.gboolean {
|
func our_window_delete_event_callback(widget *C.GtkWidget, event *C.GdkEvent, what C.gpointer) C.gboolean {
|
||||||
// called when the user tries to close the window
|
// called when the user tries to close the window
|
||||||
s := (*sysData)(unsafe.Pointer(what))
|
s := (*sysData)(unsafe.Pointer(what))
|
||||||
s.signal()
|
b := false // TODO
|
||||||
return C.TRUE // do not close the window
|
s.close(&b)
|
||||||
|
return togbool(!b) // ! because TRUE means don't close
|
||||||
}
|
}
|
||||||
|
|
||||||
var window_delete_event_callback = C.GCallback(C.our_window_delete_event_callback)
|
var window_delete_event_callback = C.GCallback(C.our_window_delete_event_callback)
|
||||||
|
@ -52,7 +53,7 @@ var window_configure_event_callback = C.GCallback(C.our_window_configure_event_c
|
||||||
func our_button_clicked_callback(button *C.GtkButton, what C.gpointer) {
|
func our_button_clicked_callback(button *C.GtkButton, what C.gpointer) {
|
||||||
// called when the user clicks a button
|
// called when the user clicks a button
|
||||||
s := (*sysData)(unsafe.Pointer(what))
|
s := (*sysData)(unsafe.Pointer(what))
|
||||||
s.signal()
|
s.event()
|
||||||
}
|
}
|
||||||
|
|
||||||
var button_clicked_callback = C.GCallback(C.our_button_clicked_callback)
|
var button_clicked_callback = C.GCallback(C.our_button_clicked_callback)
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// #include "gtk_unix.h"
|
// #include "gtk_unix.h"
|
||||||
// extern void our_dialog_response_callback(GtkDialog *, gint, gpointer);
|
|
||||||
// /* because cgo seems to choke on ... */
|
// /* because cgo seems to choke on ... */
|
||||||
// /* parent will be NULL if there is no parent, so this is fine */
|
// /* parent will be NULL if there is no parent, so this is fine */
|
||||||
// static inline GtkWidget *gtkNewMsgBox(GtkWindow *parent, GtkMessageType type, GtkButtonsType buttons, char *title, char *text)
|
// static inline GtkWidget *gtkNewMsgBox(GtkWindow *parent, GtkMessageType type, GtkButtonsType buttons, char *title, char *text)
|
||||||
|
@ -23,6 +22,11 @@ import (
|
||||||
// }
|
// }
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
|
// the actual type of these constants is GtkResponseType but gtk_dialog_run() returns a gint
|
||||||
|
var dialogResponses = map[C.gint]Response{
|
||||||
|
C.GTK_RESPONSE_OK: OK,
|
||||||
|
}
|
||||||
|
|
||||||
// dialog performs the bookkeeping involved for having a GtkDialog behave the way we want.
|
// dialog performs the bookkeeping involved for having a GtkDialog behave the way we want.
|
||||||
type dialog struct {
|
type dialog struct {
|
||||||
parent *Window
|
parent *Window
|
||||||
|
@ -30,13 +34,12 @@ type dialog struct {
|
||||||
hadgroup C.gboolean
|
hadgroup C.gboolean
|
||||||
prevgroup *C.GtkWindowGroup
|
prevgroup *C.GtkWindowGroup
|
||||||
newgroup *C.GtkWindowGroup
|
newgroup *C.GtkWindowGroup
|
||||||
result chan int
|
result Response
|
||||||
}
|
}
|
||||||
|
|
||||||
func mkdialog(parent *Window) *dialog {
|
func mkdialog(parent *Window) *dialog {
|
||||||
return &dialog{
|
return &dialog{
|
||||||
parent: parent,
|
parent: parent,
|
||||||
result: make(chan int),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,36 +62,6 @@ func (d *dialog) prepare() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *dialog) run(mk func() *C.GtkWidget) {
|
|
||||||
d.prepare()
|
|
||||||
box := mk()
|
|
||||||
if d.parent == dialogWindow {
|
|
||||||
go func() {
|
|
||||||
res := make(chan C.gint)
|
|
||||||
defer close(res)
|
|
||||||
uitask <- func() {
|
|
||||||
r := C.gtk_dialog_run((*C.GtkDialog)(unsafe.Pointer(box)))
|
|
||||||
d.cleanup(box)
|
|
||||||
res <- r
|
|
||||||
}
|
|
||||||
d.send(<-res)
|
|
||||||
}()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// otherwise just connect the delete signal
|
|
||||||
g_signal_connect_pointer(box, "response", dialog_response_callback, unsafe.Pointer(d))
|
|
||||||
C.gtk_widget_show_all(box)
|
|
||||||
}
|
|
||||||
|
|
||||||
//export our_dialog_response_callback
|
|
||||||
func our_dialog_response_callback(box *C.GtkDialog, res C.gint, data C.gpointer) {
|
|
||||||
d := (*dialog)(unsafe.Pointer(data))
|
|
||||||
d.cleanup((*C.GtkWidget)(unsafe.Pointer(box)))
|
|
||||||
go d.send(res) // send on another goroutine, like everything else
|
|
||||||
}
|
|
||||||
|
|
||||||
var dialog_response_callback = C.GCallback(C.our_dialog_response_callback)
|
|
||||||
|
|
||||||
func (d *dialog) cleanup(box *C.GtkWidget) {
|
func (d *dialog) cleanup(box *C.GtkWidget) {
|
||||||
// have to explicitly close the dialog box, otherwise wacky things will happen
|
// have to explicitly close the dialog box, otherwise wacky things will happen
|
||||||
C.gtk_widget_destroy(box)
|
C.gtk_widget_destroy(box)
|
||||||
|
@ -101,43 +74,33 @@ func (d *dialog) cleanup(box *C.GtkWidget) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *dialog) send(res C.gint) {
|
func (d *dialog) run(mk func() *C.GtkWidget) {
|
||||||
// this is where processing would go
|
d.prepare()
|
||||||
d.result <- int(res)
|
box := mk()
|
||||||
|
r := C.gtk_dialog_run((*C.GtkDialog)(unsafe.Pointer(box)))
|
||||||
|
d.cleanup(box)
|
||||||
|
d.result = dialogResponses[r]
|
||||||
}
|
}
|
||||||
|
|
||||||
func _msgBox(parent *Window, primarytext string, secondarytext string, msgtype C.GtkMessageType, buttons C.GtkButtonsType) (result chan int) {
|
func _msgBox(parent *Window, primarytext string, secondarytext string, msgtype C.GtkMessageType, buttons C.GtkButtonsType) (response Response) {
|
||||||
result = make(chan int)
|
|
||||||
d := mkdialog(parent)
|
d := mkdialog(parent)
|
||||||
uitask <- func() {
|
cprimarytext := C.CString(primarytext)
|
||||||
cprimarytext := C.CString(primarytext)
|
defer C.free(unsafe.Pointer(cprimarytext))
|
||||||
defer C.free(unsafe.Pointer(cprimarytext))
|
csecondarytext := (*C.char)(nil)
|
||||||
csecondarytext := (*C.char)(nil)
|
if secondarytext != "" {
|
||||||
if secondarytext != "" {
|
csecondarytext = C.CString(secondarytext)
|
||||||
csecondarytext = C.CString(secondarytext)
|
defer C.free(unsafe.Pointer(csecondarytext))
|
||||||
defer C.free(unsafe.Pointer(csecondarytext))
|
|
||||||
}
|
|
||||||
d.run(func() *C.GtkWidget {
|
|
||||||
return C.gtkNewMsgBox(d.pwin, msgtype, buttons, cprimarytext, csecondarytext)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
d.run(func() *C.GtkWidget {
|
||||||
|
return C.gtkNewMsgBox(d.pwin, msgtype, buttons, cprimarytext, csecondarytext)
|
||||||
|
})
|
||||||
return d.result
|
return d.result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Window) msgBox(primarytext string, secondarytext string) (done chan struct{}) {
|
func (w *Window) msgBox(primarytext string, secondarytext string) {
|
||||||
done = make(chan struct{})
|
_msgBox(w, primarytext, secondarytext, C.GtkMessageType(C.GTK_MESSAGE_OTHER), C.GtkButtonsType(C.GTK_BUTTONS_OK))
|
||||||
go func() {
|
|
||||||
<-_msgBox(w, primarytext, secondarytext, C.GtkMessageType(C.GTK_MESSAGE_OTHER), C.GtkButtonsType(C.GTK_BUTTONS_OK))
|
|
||||||
done <- struct{}{}
|
|
||||||
}()
|
|
||||||
return done
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Window) msgBoxError(primarytext string, secondarytext string) (done chan struct{}) {
|
func (w *Window) msgBoxError(primarytext string, secondarytext string) {
|
||||||
done = make(chan struct{})
|
_msgBox(w, primarytext, secondarytext, C.GtkMessageType(C.GTK_MESSAGE_ERROR), C.GtkButtonsType(C.GTK_BUTTONS_OK))
|
||||||
go func() {
|
|
||||||
<-_msgBox(w, primarytext, secondarytext, C.GtkMessageType(C.GTK_MESSAGE_ERROR), C.GtkButtonsType(C.GTK_BUTTONS_OK))
|
|
||||||
done <- struct{}{}
|
|
||||||
}()
|
|
||||||
return done
|
|
||||||
}
|
}
|
||||||
|
|
236
sysdata_unix.go
236
sysdata_unix.go
|
@ -118,42 +118,30 @@ var classTypes = [nctypes]*classData{
|
||||||
|
|
||||||
func (s *sysData) make(window *sysData) error {
|
func (s *sysData) make(window *sysData) error {
|
||||||
ct := classTypes[s.ctype]
|
ct := classTypes[s.ctype]
|
||||||
ret := make(chan *C.GtkWidget)
|
if s.alternate {
|
||||||
defer close(ret)
|
s.widget = ct.makeAlt()
|
||||||
uitask <- func() {
|
} else {
|
||||||
if s.alternate {
|
s.widget = ct.make()
|
||||||
ret <- ct.makeAlt()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ret <- ct.make()
|
|
||||||
}
|
}
|
||||||
s.widget = <-ret
|
|
||||||
if window == nil {
|
if window == nil {
|
||||||
uitask <- func() {
|
fixed := gtkNewWindowLayout()
|
||||||
fixed := gtkNewWindowLayout()
|
gtk_container_add(s.widget, fixed)
|
||||||
gtk_container_add(s.widget, fixed)
|
for signame, sigfunc := range ct.signals {
|
||||||
for signame, sigfunc := range ct.signals {
|
g_signal_connect(s.widget, signame, sigfunc, s)
|
||||||
g_signal_connect(s.widget, signame, sigfunc, s)
|
|
||||||
}
|
|
||||||
ret <- fixed
|
|
||||||
}
|
}
|
||||||
s.container = <-ret
|
s.container = fixed
|
||||||
} else {
|
} else {
|
||||||
s.container = window.container
|
s.container = window.container
|
||||||
uitask <- func() {
|
gtkAddWidgetToLayout(s.container, s.widget)
|
||||||
gtkAddWidgetToLayout(s.container, s.widget)
|
for signame, sigfunc := range ct.signals {
|
||||||
for signame, sigfunc := range ct.signals {
|
g_signal_connect(s.widget, signame, sigfunc, s)
|
||||||
g_signal_connect(s.widget, signame, sigfunc, s)
|
}
|
||||||
}
|
if ct.child != nil {
|
||||||
if ct.child != nil {
|
child := ct.child(s.widget)
|
||||||
child := ct.child(s.widget)
|
for signame, sigfunc := range ct.childsigs {
|
||||||
for signame, sigfunc := range ct.childsigs {
|
g_signal_connect(child, signame, sigfunc, s)
|
||||||
g_signal_connect(child, signame, sigfunc, s)
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
ret <- nil
|
|
||||||
}
|
}
|
||||||
<-ret
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -170,35 +158,17 @@ func (s *sysData) firstShow() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) show() {
|
func (s *sysData) show() {
|
||||||
ret := make(chan struct{})
|
gtk_widget_show(s.widget)
|
||||||
defer close(ret)
|
s.resetposition()
|
||||||
uitask <- func() {
|
|
||||||
gtk_widget_show(s.widget)
|
|
||||||
s.resetposition()
|
|
||||||
ret <- struct{}{}
|
|
||||||
}
|
|
||||||
<-ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) hide() {
|
func (s *sysData) hide() {
|
||||||
ret := make(chan struct{})
|
gtk_widget_hide(s.widget)
|
||||||
defer close(ret)
|
s.resetposition()
|
||||||
uitask <- func() {
|
|
||||||
gtk_widget_hide(s.widget)
|
|
||||||
s.resetposition()
|
|
||||||
ret <- struct{}{}
|
|
||||||
}
|
|
||||||
<-ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) setText(text string) {
|
func (s *sysData) setText(text string) {
|
||||||
ret := make(chan struct{})
|
classTypes[s.ctype].setText(s.widget, text)
|
||||||
defer close(ret)
|
|
||||||
uitask <- func() {
|
|
||||||
classTypes[s.ctype].setText(s.widget, text)
|
|
||||||
ret <- struct{}{}
|
|
||||||
}
|
|
||||||
<-ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) setRect(x int, y int, width int, height int, winheight int) error {
|
func (s *sysData) setRect(x int, y int, width int, height int, winheight int) error {
|
||||||
|
@ -208,103 +178,51 @@ func (s *sysData) setRect(x int, y int, width int, height int, winheight int) er
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) isChecked() bool {
|
func (s *sysData) isChecked() bool {
|
||||||
ret := make(chan bool)
|
return gtk_toggle_button_get_active(s.widget)
|
||||||
defer close(ret)
|
|
||||||
uitask <- func() {
|
|
||||||
ret <- gtk_toggle_button_get_active(s.widget)
|
|
||||||
}
|
|
||||||
return <-ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) text() string {
|
func (s *sysData) text() string {
|
||||||
ret := make(chan string)
|
return classTypes[s.ctype].text(s.widget)
|
||||||
defer close(ret)
|
|
||||||
uitask <- func() {
|
|
||||||
ret <- classTypes[s.ctype].text(s.widget)
|
|
||||||
}
|
|
||||||
return <-ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) append(what string) {
|
func (s *sysData) append(what string) {
|
||||||
ret := make(chan struct{})
|
classTypes[s.ctype].append(s.widget, what)
|
||||||
defer close(ret)
|
|
||||||
uitask <- func() {
|
|
||||||
classTypes[s.ctype].append(s.widget, what)
|
|
||||||
ret <- struct{}{}
|
|
||||||
}
|
|
||||||
<-ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) insertBefore(what string, before int) {
|
func (s *sysData) insertBefore(what string, before int) {
|
||||||
ret := make(chan struct{})
|
classTypes[s.ctype].insert(s.widget, before, what)
|
||||||
defer close(ret)
|
|
||||||
uitask <- func() {
|
|
||||||
classTypes[s.ctype].insert(s.widget, before, what)
|
|
||||||
ret <- struct{}{}
|
|
||||||
}
|
|
||||||
<-ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) selectedIndex() int {
|
func (s *sysData) selectedIndex() int {
|
||||||
ret := make(chan int)
|
return classTypes[s.ctype].selected(s.widget)
|
||||||
defer close(ret)
|
|
||||||
uitask <- func() {
|
|
||||||
ret <- classTypes[s.ctype].selected(s.widget)
|
|
||||||
}
|
|
||||||
return <-ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) selectedIndices() []int {
|
func (s *sysData) selectedIndices() []int {
|
||||||
ret := make(chan []int)
|
return classTypes[s.ctype].selMulti(s.widget)
|
||||||
defer close(ret)
|
|
||||||
uitask <- func() {
|
|
||||||
ret <- classTypes[s.ctype].selMulti(s.widget)
|
|
||||||
}
|
|
||||||
return <-ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) selectedTexts() []string {
|
func (s *sysData) selectedTexts() []string {
|
||||||
ret := make(chan []string)
|
return classTypes[s.ctype].smtexts(s.widget)
|
||||||
defer close(ret)
|
|
||||||
uitask <- func() {
|
|
||||||
ret <- classTypes[s.ctype].smtexts(s.widget)
|
|
||||||
}
|
|
||||||
return <-ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) setWindowSize(width int, height int) error {
|
func (s *sysData) setWindowSize(width int, height int) error {
|
||||||
ret := make(chan struct{})
|
// does not take window geometry into account (and cannot, since the window manager won't give that info away)
|
||||||
defer close(ret)
|
// thanks to TingPing in irc.gimp.net/#gtk+
|
||||||
uitask <- func() {
|
gtk_window_resize(s.widget, width, height)
|
||||||
// does not take window geometry into account (and cannot, since the window manager won't give that info away)
|
|
||||||
// thanks to TingPing in irc.gimp.net/#gtk+
|
|
||||||
gtk_window_resize(s.widget, width, height)
|
|
||||||
ret <- struct{}{}
|
|
||||||
}
|
|
||||||
<-ret
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) delete(index int) {
|
func (s *sysData) delete(index int) {
|
||||||
ret := make(chan struct{})
|
classTypes[s.ctype].delete(s.widget, index)
|
||||||
defer close(ret)
|
|
||||||
uitask <- func() {
|
|
||||||
classTypes[s.ctype].delete(s.widget, index)
|
|
||||||
ret <- struct{}{}
|
|
||||||
}
|
|
||||||
<-ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// With GTK+, we must manually pulse the indeterminate progressbar ourselves. This goroutine does that.
|
// With GTK+, we must manually pulse the indeterminate progressbar ourselves. This goroutine does that.
|
||||||
func (s *sysData) progressPulse() {
|
func (s *sysData) progressPulse() {
|
||||||
|
// TODO this could probably be done differently...
|
||||||
pulse := func() {
|
pulse := func() {
|
||||||
ret := make(chan struct{})
|
touitask(func() {
|
||||||
defer close(ret)
|
|
||||||
uitask <- func() {
|
|
||||||
gtk_progress_bar_pulse(s.widget)
|
gtk_progress_bar_pulse(s.widget)
|
||||||
ret <- struct{}{}
|
})
|
||||||
}
|
|
||||||
<-ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var ticker *time.Ticker
|
var ticker *time.Ticker
|
||||||
|
@ -345,78 +263,44 @@ func (s *sysData) setProgress(percent int) {
|
||||||
}
|
}
|
||||||
s.pulse <- false
|
s.pulse <- false
|
||||||
<-s.pulse // wait for sysData.progressPulse() to register that
|
<-s.pulse // wait for sysData.progressPulse() to register that
|
||||||
ret := make(chan struct{})
|
gtk_progress_bar_set_fraction(s.widget, percent)
|
||||||
defer close(ret)
|
|
||||||
uitask <- func() {
|
|
||||||
gtk_progress_bar_set_fraction(s.widget, percent)
|
|
||||||
ret <- struct{}{}
|
|
||||||
}
|
|
||||||
<-ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) len() int {
|
func (s *sysData) len() int {
|
||||||
ret := make(chan int)
|
return classTypes[s.ctype].len(s.widget)
|
||||||
defer close(ret)
|
|
||||||
uitask <- func() {
|
|
||||||
ret <- classTypes[s.ctype].len(s.widget)
|
|
||||||
}
|
|
||||||
return <-ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) setAreaSize(width int, height int) {
|
func (s *sysData) setAreaSize(width int, height int) {
|
||||||
ret := make(chan struct{})
|
c := gtkAreaGetControl(s.widget)
|
||||||
defer close(ret)
|
gtk_widget_set_size_request(c, width, height)
|
||||||
uitask <- func() {
|
s.areawidth = width // for sysData.preferredSize()
|
||||||
c := gtkAreaGetControl(s.widget)
|
s.areaheight = height
|
||||||
gtk_widget_set_size_request(c, width, height)
|
C.gtk_widget_queue_draw(c)
|
||||||
s.areawidth = width // for sysData.preferredSize()
|
|
||||||
s.areaheight = height
|
|
||||||
C.gtk_widget_queue_draw(c)
|
|
||||||
ret <- struct{}{}
|
|
||||||
}
|
|
||||||
<-ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO should this be made safe? (TODO move to area.go)
|
||||||
func (s *sysData) repaintAll() {
|
func (s *sysData) repaintAll() {
|
||||||
ret := make(chan struct{})
|
c := gtkAreaGetControl(s.widget)
|
||||||
defer close(ret)
|
C.gtk_widget_queue_draw(c)
|
||||||
uitask <- func() {
|
|
||||||
c := gtkAreaGetControl(s.widget)
|
|
||||||
C.gtk_widget_queue_draw(c)
|
|
||||||
ret <- struct{}{}
|
|
||||||
}
|
|
||||||
<-ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) center() {
|
func (s *sysData) center() {
|
||||||
ret := make(chan struct{})
|
if C.gtk_widget_get_visible(s.widget) == C.FALSE {
|
||||||
defer close(ret)
|
// hint to the WM to make it centered when it is shown again
|
||||||
uitask <- func() {
|
// thanks to Jasper in irc.gimp.net/#gtk+
|
||||||
if C.gtk_widget_get_visible(s.widget) == C.FALSE {
|
C.gtk_window_set_position(togtkwindow(s.widget), C.GTK_WIN_POS_CENTER)
|
||||||
// hint to the WM to make it centered when it is shown again
|
} else {
|
||||||
// thanks to Jasper in irc.gimp.net/#gtk+
|
var width, height C.gint
|
||||||
C.gtk_window_set_position(togtkwindow(s.widget), C.GTK_WIN_POS_CENTER)
|
|
||||||
} else {
|
|
||||||
var width, height C.gint
|
|
||||||
|
|
||||||
s.resetposition()
|
s.resetposition()
|
||||||
//we should be able to use gravity to simplify this, but it doesn't take effect immediately, and adding show calls does nothing (thanks Jasper in irc.gimp.net/#gtk+)
|
//we should be able to use gravity to simplify this, but it doesn't take effect immediately, and adding show calls does nothing (thanks Jasper in irc.gimp.net/#gtk+)
|
||||||
C.gtk_window_get_size(togtkwindow(s.widget), &width, &height)
|
C.gtk_window_get_size(togtkwindow(s.widget), &width, &height)
|
||||||
C.gtk_window_move(togtkwindow(s.widget),
|
C.gtk_window_move(togtkwindow(s.widget),
|
||||||
(C.gdk_screen_width() / 2) - (width / 2),
|
(C.gdk_screen_width() / 2) - (width / 2),
|
||||||
(C.gdk_screen_height() / 2) - (width / 2))
|
(C.gdk_screen_height() / 2) - (width / 2))
|
||||||
}
|
|
||||||
ret <- struct{}{}
|
|
||||||
}
|
}
|
||||||
<-ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sysData) setChecked(checked bool) {
|
func (s *sysData) setChecked(checked bool) {
|
||||||
ret := make(chan struct{})
|
gtk_toggle_button_set_active(s.widget, checked)
|
||||||
defer close(ret)
|
|
||||||
uitask <- func() {
|
|
||||||
gtk_toggle_button_set_active(s.widget, checked)
|
|
||||||
ret <- struct{}{}
|
|
||||||
}
|
|
||||||
<-ret
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ package ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// #cgo pkg-config: gtk+-3.0
|
// #cgo pkg-config: gtk+-3.0
|
||||||
|
@ -15,19 +14,32 @@ import "C"
|
||||||
|
|
||||||
var uitask chan func()
|
var uitask chan func()
|
||||||
|
|
||||||
func ui(main func()) error {
|
func uiinit() error {
|
||||||
runtime.LockOSThread()
|
|
||||||
|
|
||||||
uitask = make(chan func())
|
|
||||||
err := gtk_init()
|
err := gtk_init()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("gtk_init() failed: %v", err)
|
return fmt.Errorf("gtk_init() failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// do this only on success, just to be safe
|
||||||
|
uitask = make(chan func())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ui() {
|
||||||
// thanks to tristan and Daniel_S in irc.gimp.net/#gtk
|
// thanks to tristan and Daniel_S in irc.gimp.net/#gtk
|
||||||
// see our_idle_callback in callbacks_unix.go for details
|
// see our_idle_callback in callbacks_unix.go for details
|
||||||
go func() {
|
go func() {
|
||||||
for f := range uitask {
|
for {
|
||||||
|
var f func()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case f = <-uitask:
|
||||||
|
// do nothing
|
||||||
|
case <-Stop:
|
||||||
|
f = func() {
|
||||||
|
C.gtk_main_quit()
|
||||||
|
}
|
||||||
|
}
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
gdk_threads_add_idle(>kIdleOp{
|
gdk_threads_add_idle(>kIdleOp{
|
||||||
what: f,
|
what: f,
|
||||||
|
@ -38,11 +50,5 @@ func ui(main func()) error {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
go func() {
|
|
||||||
main()
|
|
||||||
uitask <- gtk_main_quit
|
|
||||||
}()
|
|
||||||
|
|
||||||
C.gtk_main()
|
C.gtk_main()
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue