bmx-ng / maxgui.mod

BlitzMax MaxGUI modules port.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

CreateCanvas returns Null object on latest linux (ubuntu)

markcwm opened this issue · comments

Hi,

I've NG (v0.99-3.31) installed on a 32-bit ubuntu 18.04 (bionic) and Maxgui.Gtk3maxgui examples are working but I noticed a problem. Try testing maxgui.mod/maxgui.mod/doc/createcanvas.bmx it should report 'Unhandled exception: Attempt to access field or method of Null object'.

I've tried using the old Bah.Gtkmaxgui but I can't get it to run, it just says 'identifier Driver not found'. I use Gtk1 on my older ubuntu 16.04 install with no problems, I don't think I've tried using Gtk3 there so I'll get back to you on that.

Ah yes, it doesn't build on 16.04 ubuntu. I get:

Compile Error: Identifier 'systemdriver' not found.
[~/bmx-ng/mod/gtk.mod/gtk3maxgui.mod/gtkgadget.bmx;4007;0]

I checked for dependencies with 'dpkg -L libgtk-3-0' and libgtk-3-dev and they're installed.

Dunno if this is the same but with NG maxgui.bmx's code:

Function CreateCanvas:TGadget( x,y,w,h,group:TGadget,style=0 )
	Local t:TGadget=maxgui_driver.CreateGadget(GADGET_CANVAS,"",x,y,w,h,GetGroup(group),style)
	Assert t, "maxgui_driver.CreateGadget failed" 'added by me
	t.AttachGraphics DefaultGraphicsFlags()	'gfxFlags
	Return t
End Function

asserts that canvas wasn't created too on my linux box. With vanilla it works. Also on Windows the very same code works.
The code uses "Brl.Timer" and "Brl.GLMax2D", so no SDL.

gtk3maxgui.mod/gtkgadget.bmx contains a TGTKCanvas which is commented out - also other occourences of TGTKCanvas are rem'd.

Might explain why this does not work yet.

Open maxgui.mod/gtk3maxgui.mod/gtkcommon.bmx and add to the "extern" part:

	Function gdk_x11_window_get_xid:Byte Ptr(handle:Byte Ptr)

Open gtkgadget.bmx in the same folder and replace the function:

	Method CanvasGraphics:TGraphics()
		If Not canvas Then
			canvas = BRL.Graphics.AttachGraphics(gdk_x11_window_get_xid(gtk_widget_get_window(handle)), Mode)
		End If

		Return canvas
	End Method

(it replaces "gdk_x11_drawable_get_xid" with the corresponding gtk3 function "gdk_x11_window_get_xid" (they BOTH rely on the existence of X11 - so wayland-using distributions are out).

In the "Method initCanvas" of the very same file I replaced the event connections:

		addConnection("button-press-event", g_signal_cb3_ret(handle, "button-press-event", OnMouseDown, Self, Destroy, 0))
		addConnection("button-release-event", g_signal_cb3_ret(handle, "button-release-event", OnMouseUp, Self, Destroy, 0))
		addConnection("enter-notify-event", g_signal_cb3_ret(handle, "enter-notify-event", OnMouseEnter, Self, Destroy, 0))
		addConnection("leave-notify-event", g_signal_cb3_ret(handle, "leave-notify-event", OnMouseLeave, Self, Destroy, 0))
		addConnection("motion-notify-event", g_signal_cb3_ret(handle, "motion-notify-event", OnMouseMove, Self, Destroy, 0))
		addConnection("scroll-event", g_signal_cb3(handle, "scroll-event", OnScroll, Self, Destroy, 0))

		addConnection("key-press-event", g_signal_cb3_ret(handle, "key-press-event", OnKeyDown, Self, Destroy, 0))
		addConnection("key-release-event", g_signal_cb3_ret(handle, "key-release-event", OnKeyUp, Self, Destroy, 0))

Remove the Rem/EndRem from:

Rem
			Case GTK_CANVAS
				gadget = TGTKCanvas.CreateCanvas(x, y ,w , h, label, group, style)
End Rem

and around the type: Type TGTKCanvas Extends TGTKGadget

It now compiled properly - but the canvas stood empty (in my application it contained a scrollbar then - once scrolled the canvas went black, so it did not work as expected). In your sample app I received some events but nothing was drawn.

-> EVENT_GADGETPAINT is not triggered/emitted

Maybe that still helps.

I manually added a new "addConnection" to react to "draw" events.
Result was a black-canvas wit white arrows - a bit flickering.

...
		addConnection("draw", g_signal_cb3_ret(handle, "draw", OnDraw, Self, Destroy, 0))
...


	Function OnDraw:Int(widget:Byte Ptr, cairo:Byte Ptr, obj:Object)
		PostGuiEvent(EVENT_GADGETPAINT, TGadget(obj))
	End Function

Maybe we need to implement GtkDrawingArea?
https://developer.gnome.org/gtk3/stable/GtkDrawingArea.html

Edit: when exiting the app I receive:
GLib-GObject-WARNING **: /build/glib2.0-7ZsPUq/glib2.0-2.48.2/./gobject/gsignal.c:2517: signal 'expose_event' is invalid for instance '0x15ae2e0' of type 'GtkDrawingArea'
-> removing the for now inactive

		addConnection("expose_event", g_signal_cb3(handle, "expose_event", CanvasRedraw, Self, Destroy, 0))

removes that message.

Sorry for spamming ;-)

I added SetClsColor 255,255,255 in the createcanvas.bmx before doing the cls. The result was an alternating display of full-black or full-white (as the arrows there white too). It looks as if only every second frame was "drawn".

Thanks for the help Ron, definitely not spam. :)

Well, I tried your code but I just can't get it to run, I keep getting the 'Null object' error from CreateGadget in Maxgui.Maxgui.

I did notice the error 'identifier Driver not found' means the module just isn't built/defined.

A real shame this isn't fixed yet.

Did above - but replaced the "draw"-event connection as I mistakingly used g_signal_cb3_ret but as CanvasRedraw does not return anything it has to be g_signal_cb3. So this step should only be then:

		'Ronny: in GTK3 this is "draw"
		'addConnection("expose_event", g_signal_cb3(handle, "expose_event", CanvasRedraw, Self, Destroy, 0))
		addConnection("draw", g_signal_cb3(handle, "draw", CanvasRedraw, Self, Destroy, 0))

(diff file: gtk3patch.txt)

result is still this:

canvas

Edit: extended the sample to also react to "resizing" (as this for me sometimes creates "black borders").

' createcanvas.bmx
SuperStrict
Framework Brl.StandardIO
Import Brl.SystemDefault
Import BRL.EventQueue
Import BRL.GLMax2D
Import Brl.TimerDefault
Import MaxGui.GTK3MaxGUI
Import MaxGui.Drivers

Global GAME_WIDTH:Int=320
Global GAME_HEIGHT:Int=240

' create a centered window with client size GAME_WIDTH,GAME_HEIGHT

Local wx:Int=(ClientWidth(Desktop())-GAME_WIDTH)/2
Local wy:Int=(ClientHeight(Desktop())-GAME_HEIGHT)/2

Local window:TGadget=CreateWindow("My Canvas",wx,wy,GAME_WIDTH,GAME_HEIGHT,Null,WINDOW_TITLEBAR|WINDOW_RESIZABLE)'|WINDOW_CLIENTCOORDS)

' create a canvas for our game
Local canvas:TGadget=CreateCanvas(0,0,320,240,window)
' scale canvas with window
SetGadgetLayout canvas,EDGE_ALIGNED,EDGE_ALIGNED,EDGE_ALIGNED,EDGE_ALIGNED

' create an update timer
CreateTimer 60

While WaitEvent()
	Select EventID()
		Case EVENT_TIMERTICK
			RedrawGadget canvas

		Case EVENT_WINDOWSIZE
			GAME_WIDTH = GadgetWidth(canvas)
			GAME_HEIGHT = GadgetHeight(canvas)

		Case EVENT_GADGETPAINT
			SetGraphics CanvasGraphics(canvas)
			SetViewport 0,0, GAME_WIDTH, GAME_HEIGHT
			SetOrigin 0,0
			SetColor 255,0,0
			DrawRect(0,0, GAME_WIDTH, GAME_HEIGHT)
			SetColor 255,255,255
			SetOrigin 160,120
			SetLineWidth 5
'			Cls
			Local t:Int=MilliSecs()
			DrawLine 0,0,Float(120*Cos(t)),Float(120*Sin(t))
			DrawLine 0,0,Float(80*Cos(t/60)),Float(80*Sin(t/60))
			Flip

		Case EVENT_MOUSEMOVE
			Print "MOVE!"

		Case EVENT_WINDOWCLOSE
			FreeGadget canvas
			End

		Case EVENT_APPTERMINATE
			End
	End Select
Wend

blackborders

to fix this, I need to use "GadgetWidth()" (or the assignment) in each paint.

		Case EVENT_GADGETPAINT
			SetGraphics CanvasGraphics(canvas)
			GAME_WIDTH = GadgetWidth(canvas)
			GAME_HEIGHT = GadgetHeight(canvas)
			SetViewport 0,0, GAME_WIDTH, GAME_HEIGHT

So the RESIZE-event will possibly not have all the gadget values calculated already.

Having applied the diff file; I can confirm that it works.
Well done @GWRon

@markcwm
why do you close it ? The PR is not merged - so the issue should still be open.

OK, sorry, just that I consider this done.