1package gtk 2 3// #include <gtk/gtk.h> 4// #include "gtk.go.h" 5import "C" 6import ( 7 "errors" 8 "os" 9 "unsafe" 10 11 "github.com/gotk3/gotk3/gdk" 12 13 "github.com/gotk3/gotk3/glib" 14) 15 16// TestFindLabel is a wrapper around gtk_test_find_label(). 17// This function will search widget and all its descendants for a GtkLabel widget with a text string matching label_pattern. 18// The labelPattern may contain asterisks “*” and question marks “?” as placeholders, g_pattern_match() is used for the matching. 19func TestFindLabel(widget IWidget, labelPattern string) (IWidget, error) { 20 cstr := C.CString(labelPattern) 21 defer C.free(unsafe.Pointer(cstr)) 22 c := C.gtk_test_find_label(widget.toWidget(), (*C.gchar)(cstr)) 23 if c == nil { 24 return nil, errors.New("no label with pattern '" + labelPattern + "' found") 25 } 26 obj, err := castWidget(c) 27 if err != nil { 28 return nil, err 29 } 30 return obj, nil 31} 32 33// TestFindSibling is a wrapper around gtk_test_find_sibling(). 34// This function will search siblings of base_widget and siblings of its ancestors for all widgets matching widgetType. 35// Of the matching widgets, the one that is geometrically closest to base_widget will be returned. 36func TestFindSibling(baseWidget IWidget, widgetType glib.Type) (IWidget, error) { 37 c := C.gtk_test_find_sibling(baseWidget.toWidget(), C.GType(widgetType)) 38 if c == nil { 39 return nil, errors.New("no widget of type '" + widgetType.Name() + "' found") 40 } 41 obj, err := castWidget(c) 42 if err != nil { 43 return nil, err 44 } 45 return obj, nil 46} 47 48// TestFindWidget is a wrapper around gtk_test_find_widget(). 49// This function will search the descendants of widget for a widget of type widget_type that has a label matching labelPattern next to it. 50// This is most useful for automated GUI testing, e.g. to find the “OK” button in a dialog and synthesize clicks on it. 51// However see TestFindLabel(), TestFindSibling() and TestWidgetClick() (and their GTK documentation) 52// for possible caveats involving the search of such widgets and synthesizing widget events. 53func TestFindWidget(widget IWidget, labelPattern string, widgetType glib.Type) (IWidget, error) { 54 cstr := C.CString(labelPattern) 55 defer C.free(unsafe.Pointer(cstr)) 56 c := C.gtk_test_find_widget(widget.toWidget(), (*C.gchar)(cstr), C.GType(widgetType)) 57 if c == nil { 58 return nil, errors.New("no widget with label pattern '" + labelPattern + "' and type '" + widgetType.Name() + "' found") 59 } 60 obj, err := castWidget(c) 61 if err != nil { 62 return nil, err 63 } 64 return obj, nil 65} 66 67/* 68TestInit is a wrapper around gtk_test_init(). 69This function is used to initialize a GTK+ test program. 70It will in turn call g_test_init() and gtk_init() to properly initialize the testing framework and graphical toolkit. 71It’ll also set the program’s locale to “C” and prevent loading of rc files and Gtk+ modules. 72This is done to make tets program environments as deterministic as possible. 73 74Like gtk_init() and g_test_init(), any known arguments will be processed and stripped from argc and argv. 75*/ 76func TestInit(args *[]string) { 77 if args != nil { 78 argc := C.int(len(*args)) 79 argv := C.make_strings(argc) 80 defer C.destroy_strings(argv) 81 82 for i, arg := range *args { 83 cstr := C.CString(arg) 84 C.set_string(argv, C.int(i), (*C.gchar)(cstr)) 85 } 86 87 C._gtk_test_init((*C.int)(unsafe.Pointer(&argc)), 88 (***C.char)(unsafe.Pointer(&argv))) 89 90 unhandled := make([]string, argc) 91 for i := 0; i < int(argc); i++ { 92 cstr := C.get_string(argv, C.int(i)) 93 unhandled[i] = goString(cstr) 94 C.free(unsafe.Pointer(cstr)) 95 } 96 *args = unhandled 97 } else { 98 // gtk_test_init does not take nil, we have to use an empty argument list 99 // (only containing the first arg, which is the executable name) 100 argc := C.int(1) 101 argv := C.make_strings(argc) 102 defer C.destroy_strings(argv) 103 104 // Add first argument 105 cstr := C.CString(os.Args[0]) 106 C.set_string(argv, C.int(0), (*C.gchar)(cstr)) 107 108 C._gtk_test_init((*C.int)(unsafe.Pointer(&argc)), 109 (***C.char)(unsafe.Pointer(&argv))) 110 } 111} 112 113// TestListAllTypes is a wrapper around gtk_test_list_all_types(). 114// Return the type ids that have been registered after calling TestRegisterAllTypes(). 115func TestListAllTypes() []glib.Type { 116 var types *C.GType 117 var clen C.guint 118 119 types = C.gtk_test_list_all_types(&clen) 120 defer C.free(unsafe.Pointer(types)) 121 122 length := uint(clen) 123 124 typeReturn := make([]glib.Type, length) 125 for i := uint(0); i < length; i++ { 126 current := (*C.GType)(pointerAtOffset(unsafe.Pointer(types), unsafe.Sizeof(*types), i)) 127 typeReturn[i] = glib.Type(*current) 128 } 129 return typeReturn 130} 131 132// pointerAtOffset adjusts `arrayPointer` (pointer to the first element of a C array) 133// to point at the offset `i`, 134// to be able to read the value there without having to go through cgo. 135func pointerAtOffset(arrayPointer unsafe.Pointer, elementSize uintptr, offset uint) unsafe.Pointer { 136 return unsafe.Pointer(uintptr(arrayPointer) + elementSize*uintptr(offset)) 137} 138 139// TestRegisterAllTypes is a wrapper around gtk_test_register_all_types(). 140// Force registration of all core Gtk+ and Gdk object types. 141// This allowes to refer to any of those object types via g_type_from_name() after calling this function. 142func TestRegisterAllTypes() { 143 C.gtk_test_register_all_types() 144} 145 146// TestWidgetSendKey is a wrapper around gtk_test_widget_send_key() 147// 148// This function will generate keyboard press and release events 149// in the middle of the first GdkWindow found that belongs to widget. 150// For windowless widgets like GtkButton (which returns FALSE from gtk_widget_get_has_window()), 151// this will often be an input-only event window. 152// For other widgets, this is usually widget->window. 153// 154// widget: Widget to generate a key press and release on. 155// keyval: A Gdk keyboard value. 156// modifiers: Keyboard modifiers the event is setup with. 157// 158// returns: whether all actions neccessary for the key event simulation were carried out successfully. 159func TestWidgetSendKey(widget IWidget, keyval uint, modifiers gdk.ModifierType) bool { 160 return gobool(C.gtk_test_widget_send_key(widget.toWidget(), C.guint(keyval), C.GdkModifierType(modifiers))) 161} 162