Skip to content
client-demo.c 3.96 KiB
Newer Older
/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <gio/gio.h>
#include <locale.h>
#include <glib.h>
#ifdef G_OS_UNIX
#include <glib-unix.h>
#endif
#include "zero-panel.h"

typedef struct {
	GApplication *app;
	ZeroPanel *proxy;
} AppData;

AppData appdata;

#ifdef G_OS_UNIX
/**
 * handle SIGTERM gracefully.
 */
static gboolean
on_sigterm_received(gpointer user_data)
{
	AppData *appdata = (AppData *) user_data;
	g_application_quit(appdata->app);
	return G_SOURCE_REMOVE;
}

/**
 * allow graceful shutdown by Ctrl-C and SIGTERM.
 */
static void
setup_sigint_sigterm_handler(AppData *appdata)
{
	GSource *source = NULL;
	source = g_unix_signal_source_new(SIGTERM);
	g_source_set_callback(source, on_sigterm_received, appdata, NULL);
	g_source_attach(source, NULL);
	g_source_unref(source);

	source = g_unix_signal_source_new(SIGINT);
	g_source_set_callback(source, on_sigterm_received, appdata, NULL);
	g_source_attach(source, NULL);
	g_source_unref(source);
}
#endif

static gint
hide_then_quit(gpointer user_data)
{
	AppData *appdata = (AppData *) user_data;
	GError *err = NULL;
	zero_panel_call_hide_sync(appdata->proxy, NULL, &err);
	if (err) {
		g_warning("call Hide() failed: %s", err->message);
		g_error_free(err);
	} else {
		g_message("call Hide() okay");
		g_application_quit(appdata->app);
	}
	return G_SOURCE_REMOVE;
}

static void
startup(GApplication *app,
	AppData *appdata)
{
	ZeroPanel *proxy = NULL;
	GError *err = NULL;

#ifdef G_OS_UNIX
	setup_sigint_sigterm_handler(appdata);
#endif

	appdata->proxy = NULL;
	proxy = zero_panel_proxy_new_for_bus_sync(
			G_BUS_TYPE_SESSION,
			G_DBUS_PROXY_FLAGS_NONE,
			ZERO_PANEL_WELL_KNOWN_NAME,
			ZERO_PANEL_OBJECT_PATH,
			NULL,		/* GCancellable */
			&err);
	if (err) {
		g_warning("connect to zero panel proxy failed: %s", err->message);
		g_error_free(err);
	} else {
		appdata->proxy = proxy;
	}

	/* show panel, wait 3s, then hide panel and exit app */
	err = NULL;
	const gchar *const candidates[] = {"第一个", "第二个", "第三个"};
	GVariant *hints = NULL;
	GVariantBuilder b = {0};
	g_variant_builder_init(&b, G_VARIANT_TYPE("a{sv}"));
	g_variant_builder_add(&b, "{sv}", "has_next_page",
			      g_variant_new_boolean(TRUE));
	g_variant_builder_add(&b, "{sv}", "has_previous_page",
			      g_variant_new_boolean(FALSE));
	hints = g_variant_builder_end(&b);
	zero_panel_call_show_candidates_sync(proxy, "abc", 3, candidates, hints, NULL, &err);
	if (err) {
		g_warning("call ShowCandidates() failed: %s", err->message);
		g_error_free(err);
	} else {
		g_message("call ShowCandidates() okay");
		g_timeout_add_seconds(3, hide_then_quit, appdata);
	}

	g_application_hold(app);
}

static void
activate(GApplication *app,
	 AppData *appdata)
{
	g_message("activate()");
	/* activate is a no-op. */
}

static void
shutdown(GApplication *app,
	 AppData *appdata)
{
	g_message("shutdown()");
	if (appdata->proxy) {
		zero_panel_call_hide(appdata->proxy, NULL, NULL, NULL);
		g_object_unref(appdata->proxy);
		appdata->proxy = NULL;
	}
}

int
main(int argc, char *argv[])
{
	GApplication *app = NULL;
	int status = 0;

	setlocale(LC_ALL, "");
	app = g_application_new("com.emacsos.zero.ZeroPanelClientDemo", 0);
	g_assert_nonnull(app);
	appdata.app = app;
	g_signal_connect(app, "startup", G_CALLBACK(startup), &appdata);
	g_signal_connect(app, "activate", G_CALLBACK(activate), &appdata);
	g_signal_connect(app, "shutdown", G_CALLBACK(shutdown), &appdata);

	status = g_application_run(G_APPLICATION(app), argc, argv);
	g_object_unref(app);
	return status;
}