GLib signal connect works with webkitgtk but not webkitgtk2 - gtk

I am working on a web browser for fun and ran into this problem.
This works:
#include <webkit/webkit.h>
void init() {
GtkWidget *web_view = webkit_web_view_new();
g_signal_connect(
G_OBJECT(GTK_WIDGET(this->web_view)),
"notify::progress",
G_CALLBACK(LoadChangedProxy),
NULL);
webkit_web_view_load_uri(WEBKIT_WEB_VIEW(this->web_view), "http://google.com");
}
void LoadChangedProxy(GtkWidget *view, GParamSpec *pspec, gpointer p) {
puts("LOADING");
}
In this case the callback is never called:
#include <webkit2/webkit2.h>
void init() {
GtkWidget *web_view = webkit_web_view_new();
g_signal_connect(
G_OBJECT(GTK_WIDGET(this->web_view)),
"notify::estimated-load-progress",
G_CALLBACK(LoadChangedProxy),
NULL);
webkit_web_view_load_uri(WEBKIT_WEB_VIEW(this->web_view), "http://google.com");
}
void LoadChangedProxy(GtkWidget *view, GParamSpec *pspec, gpointer p) {
puts("LOADING");
}
I was attempting to use webkitgtk2 initially and was really hitting my head against the wall. I switched to the older webkitgtk1 header and api and it magically started working. I have not idea what would cause this, additionally no errors are printed to stderr or stdout (eg. attempting to connect to a signal that an object does not have).
Any suggestions out there? There is surprisingly little documentation on g_signal_connect, from glib. All I know has come from looking at some gnome app source code.
Edit:
I have found that using "notify::progress" signal identifier in the webkitgtk2 case, the callback works. However I then cannot use either webkit_web_view_get_progress() or webkit_web_view_get_estimated_load_progress() to read the progress value to display it.

The symptoms are strange enough that I can only think of one explanation: you are still linking with webkit-gtk. With trivial code like this you didn't happen to hit linking problems but of course the new signals wouldn't be there either.

Related

GtkApplicationWindow subclass "destroy" twice

I took the application1 from examples in Gtk source
and modified GtkApplicationWindow subclass as to save some window state in the "destroy" signal handler. The problem with my code is that the save_some_state() is called twice. Why? How can I fix it?
static void
example_app_activate (GApplication *app) {
ExampleAppWindow *win;
win = example_app_window_new (EXAMPLE_APP (app));
gtk_window_present (GTK_WINDOW (win));
}
........
static void
on_app_window_destroy (GtkWidget* widget)
{
ExampleAppWindow* win = EXAMPLE_APP_WINDOW(widget);
save_some_state(win);
GTK_WIDGET_CLASS(example_app_window_parent_class)->destroy (widget);
}
static void
example_app_window_class_init (ExampleAppWindowClass *klass)
{
GtkWidgetClass* widget_class = GTK_WIDGET_CLASS (klass);
widget_class->destroy = on_app_window_destroy;
}
Well, it definitely looks like you are destroying it twice by calling
GTK_WIDGET_CLASS(example_app_window_parent_class)->destroy (widget);
in the on_app_window_destroy callback
Where are you storing example_app_window_parent_class? Is this derived from the widget? As GtkNerd says it may duplicate things if it is not chained right.
I am not entirely confident of the internals. For Gtk2, destroy is a GtkObject signal not a GtkWidget signal so you would cast as GTK_OBJECT_CLASS in that case, though that is likely irrelevant - For Gtk3 it is fine as is. I am not sure about the internals but the destroy signal might get called multiple times due to reference counting. A safer option is to override finalize as it should only get called the once irrespective.

class "APlayerController" has no member "GetPlayerViewPoint" in UE4.21.2

I'm in UE4 4.21.2
I'm a total noob for UE4. I'm following along with a tutorial where I need to use the GetPlayerViewPoint method on the PlayerController class, however when I try and call that method, I get a compile time error that says: class "APlayerController" has no member "GetPlayerViewPoint"
Which is weird because I get autocomplete in Visual Studio for other methods on that class, but not that particular method, BUT I can see that method in the docs here:
http://api.unrealengine.com/INT/API/Runtime/Engine/GameFramework/APlayerController/index.html
Could it be that my compiler and autocomplete are using a different UE4 version than the docs and tutorial?
Anyways, here is my class.
// Copyright, 2018
#include "BryceEscapeRoomUe4.h"
#include "Grabber.h"
#include "Runtime/Engine/Classes/GameFramework/Actor.h"
#include "Engine/World.h";
#include "GameFramework/PlayerController.h"
#define OUT
// Sets default values for this component's properties
UGrabber::UGrabber()
{
// Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features
// off to improve performance if you don't need them.
PrimaryComponentTick.bCanEverTick = true;
// ...
}
// Called when the game starts
void UGrabber::BeginPlay()
{
Super::BeginPlay();
UE_LOG(LogTemp, Warning, TEXT("Grabber repoting for duty!"));
}
// Called every frame
void UGrabber::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
// get player view point this tick
FVector PlayerVeiwPointLocation;
FRotator PlayerVeiwPointRotaion;
GetWorld()->GetFirstPlayerController()->GetPlayerVeiwPoint(
OUT PlayerVeiwPointLocation,
OUT PlayerVeiwPointRotaion
);
//log out to test
//ray cast out to reach distance
// see what we hit
}
I think this may have been caused by the fact that you have spelled GetPlayerViewPoint as GetPlayerVeiwPoint, which isn't a method that exists in UE4. Hopefully that should fix the problem, although as this is a relatively old question I'm sure you figured that out a while ago!

Facebook Unity SDK FB.Feed causes NullReferenceException

I'm having a problem when using the Facebook Unity API, calling the FB.Feed() method. It winds up giving this error:
NullReferenceException: Object reference not set to an instance of an object
UnityEngine.GUILayoutUtility.DoGetRect (UnityEngine.GUIContent content,
UnityEngine.GUIStyle style, UnityEngine.GUILayoutOption[] options) (at
C:/BuildAgent/work/d3d49558e4d408f4/artifacts/EditorGenerated/GUILayoutUtility.cs:264)
which is immediately followed by:
ArgumentException: Getting control 1's position in a group with only 1 controls
when doing Repaint
I know the second error is usually caused in Unity by GUI elements changing between GUI event calls, etc. In my case, however, I'm not doing anything within OnGUI at all. In fact, because of tearing my hair out trying to figure out what the problem is, I created a totally new project - 1 scene with basic buttons to login, and then "brag" using the FB.Feed. I've written it the exact way that their documents show, and I get the exact same error.
I'm hoping maybe someone might be able to shed some light on what I'm missing or doing wrong.
Here is complete code in my simple barebones scene that also causes this error:
void Start()
{
FB.Init(OnInitComplete, OnHideUnity);
}
void OnInitComplete()
{
Debug.Log("FB Initialized");
}
void OnHideUnity(bool isGameShown)
{
Debug.Log("OnHideUnity");
if (!isGameShown)
Time.timeScale = 0;
else
Time.timeScale = 1;
}
void Update()
{
}
void OnGUI()
{
if (!FB.IsLoggedIn)
{
if (GUI.Button(new Rect(10, 10, 100, 30), "Login"))
FBLogin();
}
else
{
if (GUI.Button(new Rect(10, 50, 100, 30), "Brag"))
{
Brag();
}
}
}
void Brag()
{
FB.Feed(
linkCaption: "This is testing the testapp FEED",
picture: "http://myapp.com/myapplogo.jpg",
linkName: "Foo Link",
link: "http://apps.facebook.com/" + FB.AppId + "/?challenge_brag=" + (FB.IsLoggedIn ? FB.UserId : "guest")
);
}
void FBLogin()
{
FB.Login("email, publish_actions", OnLoggedIn);
}
void OnLoggedIn(FBResult result)
{
if (FB.IsLoggedIn)
Debug.Log("Logged in successfully");
}
My Facebook API is version 140220, and my Unity is 4.3.4
I'll do my best to answer any other questions for info I've missed
I've also tried using the FB API version 131022, and have the same results.
This error also happens with the FriendSmash example and as well with the InteractiveConsole example scene provided with the plugin.
I should also point out that the Window does open for the post, and loads the image, link, etc. The exception prevents anything else from working however
Additional Info: I've found that when the app is ran on an actual android device, the feed post works with no problem. It only appears to have this error within the Unity editor. I have another issue with test users logging in on the android device - they can't if the device has the Facebook app itself installed, but that issue probably warrants a separate question
I think it's just not getting all of the resources it's asking for. The docs say not to worry about it, the editor can only do so much. I get the one below. Unfortunately though, mine is not working on the device, but if yours is, I wouldn't worry about it too much.
NullReferenceException: Object reference not set to an instance of an object
UnityEngine.GUILayoutUtility.DoGetRect (UnityEngine.GUIContent content, UnityEngine.GUIStyle style, UnityEngine.GUILayoutOption[] options) (at C:/BuildAgent/work/d3d49558e4d408f4/artifacts/EditorGenerated/GUILayoutUtility.cs:264)
UnityEngine.GUILayoutUtility.GetRect (UnityEngine.GUIContent content, UnityEngine.GUIStyle style) (at C:/BuildAgent/work/d3d49558e4d408f4/artifacts/EditorGenerated/GUILayoutUtility.cs:257)
Facebook.FbSkinnedDialog.TwoButtonBar (System.String label, System.String cancelLabel)
Facebook.FeedDialog.UpdateDialog (Int32 windowID)
Facebook.FbSkinnedDialog.GeneralUpdateDialog (Int32 windowId)
UnityEngine.GUI.CallWindowDelegate (UnityEngine.WindowFunction func, Int32 id, UnityEngine.GUISkin _skin, Int32 forceRect, Single width, Single height, UnityEngine.GUIStyle style) (at C:/BuildAgent/work/d3d49558e4d408f4/artifacts/EditorGenerated/GUI.cs:1395)

Why is the signal callback data pointer pointing to a junk value when the callback is fired?

Ok, I'm writing a method that creates an entire panel and it's containing contents and adds it to the form. The panels are stored in an array.
Here's the basic idea.
void vscale1Event(GtkWidget *widget, int *vscale_id)
{
int value = gtk_range_get_value(GTK_RANGE(vscale_struct[*vscale_id]->vscale1));
do stuff with this value;
}
void add_vscale_panel(int vscale_id)
{
vscale_struct[vscale_id]->vscale1 = ..... ;
vscale_struct[vscale_id]->vscale2 = ..... ;
add buttons to form;
gtk_signal_connect(GTK_OBJECT(vscale_struct[button_id]), "value_changed", (GtkSignalFunc)vscale1Event, &vscale_id);
gtk_signal_connect(GTK_OBJECT(vscale_struct[button_id]), "value_changed", (GtkSignalFunc)vscale2Event, &vscale_id);
}
int main()
{
for (i = 0; i<n; i++)
{
add_vscale_panel(i);
}
}
The problem I'm having, is that &vscale_id that I'm passing in, later becomes junk (it's value is a junk number around 32000) when I move the scale.
But - the gtk_signal_connect is only being called that once.
Ok, I get that it's probably something to do with the call stack, that bit of memory no longer being reserved.
But I did this same thing earlier for another panel, and it's working fine.
what I've changed - is trying to make things a bit tidier.
The previous version I had all the panels and widgets each in seperate arrays.
eg
GtkWidget **outerPanel;
GtkWidget **innerPanel1;
GtkWidget **vscale1;
whereas this one I'm doing it:
typedef struct
{
GtkWidget **vscale1;
Gtkwidget **vscale2;
} V_Panel;
V_Panel **vscale_struct;
Not bothering putting the panels into arrays or structs - because I figure I don't need to access them later? ( I found that you can 'recycle' labels so I figure panels (h and vboxes), are the same.
Also - an interesting clue - when I run valgrind - it works fine. Some how valgrind changes the way the program uses it's memory.
Any help here?
If you can perhaps explain what's happening when you call gtk_signal_connect. -
Here's my actual code: http://pastebin.com/MGfUihjM
relevant lines are
45, 145, 274, 308, 391
The problem is that your taking the address of a variable on the stack - in this case the parameter to the function. That address in memory is definitely not guaranteed to continue to hold the value you expect it to since it is just part of the stack frame
The correct way to pack your integer value_id into the callback userdata pointer is to use GINT_TO_POINTER and to reverse it using GPOINTER_TO_INT.
So your signal connection would be:
gtk_signal_connect(GTK_OBJECT(vscale_struct[button_id]),
"value_changed",
(GtkSignalFunc)vscale1Event,
GINT_TO_POINTER(value_id));
And in your signal handler would look like:
void vscale1Event(GtkWidget *widget, gpointer userdata)
{
int vscale_id = GPOINTER_TO_INT (userdata);
int value = gtk_range_get_value(GTK_RANGE(vscale_struct[vscale_id]->vscale1));
do stuff with this value;
}

Do I have to manually attach a gtk signal handler when I specified the function name in glade?

I'm writing my first gtk program, using gtkmm, and glade.
I made a filechooserbutton and it has a signal called file-set
So I set that to what I assume is the function name I want it to call when the file is chosen.
But then I see here:
http://library.gnome.org/devel/gtkmm-tutorial/unstable/sec-builder-accessing-widgets.html.en
That they're manually getting the dialog widget and setting a button signal handler in the code.
Which is the right way to do it?
And while I'm here any links to good examples would be handy, they seem to be few and far between. Thanks.
This is how I did it:
// create the UI
refUI = Gtk::Builder::create();
refUI->add_from_file(grq::GLADE_FILE);
// grab your widget
refUI->get_widget("but_new", but_new); // Gtk::ToolButton *but_new;
but_new->signal_clicked().connect(sigc::mem_fun(*this, &MainWindow::on_new_game));
// your signal handler looks something like this :)
void MainWindow::on_new_game() {}
edit:
Basically the *this is the object on which you will be calling the function your signal handler.
This is what my main looks like:
int main(int argc, char **argv) {
Gtk::Main kit(argc, argv);
MainWindow main_window;
kit.run(*main_window.window);
return 0;
}
MainWindow is basically a class that wraps GtkWindow and defines the widgets, a. la.:
class MainWindow
{
private:
Glib::RefPtr<Gtk::Builder> refUI;
//
// Widgets
//
Gtk::ToolButton *but_about;
public:
// The window. This is public so we can hook into events and
// call kit.run(window) against it, if needed.
Gtk::Window *window;
MainWindow()
{
// Load the data for this window and it's widgets.
refUI = Gtk::Builder::create();
refUI->add_from_file(grq::GLADE_FILE);
// The window
refUI->get_widget("main_window", window);
// Widgets
refUI->get_widget("but_about", but_about);
but_about->signal_clicked().connect(sigc::mem_fun(*this, &MainWindow::on_about));
...
}
virtual ~MainWindow()
{
if (window != NULL)
{
delete window; // Frees all the children for the window, too.
}
}
virtual void on_about()
{
// stuff
}
};
Hope this helps!
I found the answer to my question as an afterthought in another stackoverflow question.
But I don't remember which one it was.
The answer seems to be that you have to programmatically add the signal handler to the widget in your code, the gtkbuilder won't do it for you.