static gboolean on_new_connection (GSocketService *service, GSocketConnection *socket_connection, GObject *source_object, DasomServer *server) { g_debug (G_STRLOC ": %s", G_STRFUNC); /* TODO: simple authentication using GCredentials */ GSocket *socket = g_socket_connection_get_socket (socket_connection); DasomMessage *message; message = dasom_recv_message (socket); if (message->header->type == DASOM_MESSAGE_CONNECT) dasom_send_message (socket, DASOM_MESSAGE_CONNECT_REPLY, NULL, 0, NULL); else { /* TODO: error handling */ dasom_send_message (socket, DASOM_MESSAGE_ERROR, NULL, 0, NULL); return TRUE; /* TODO: what happened if return value is FALSE */ } DasomConnection *connection; connection = dasom_connection_new (*(DasomConnectionType *) message->data, dasom_server_get_default_engine (server), NULL); dasom_message_unref (message); connection->socket = socket; dasom_server_add_connection (server, connection); if (connection->type == DASOM_CONNECTION_DASOM_AGENT) server->agents_list = g_list_prepend (server->agents_list, connection); connection->source = g_socket_create_source (socket, G_IO_IN, NULL); connection->socket_connection = g_object_ref (socket_connection); g_source_set_can_recurse (connection->source, TRUE); g_source_set_callback (connection->source, (GSourceFunc) on_incoming_message_dasom, connection, NULL); g_source_attach (connection->source, server->main_context); return TRUE; }
gboolean dasom_im_get_surrounding (DasomIM *im, gchar **text, gint *cursor_index) { g_debug (G_STRLOC ": %s", G_STRFUNC); g_return_val_if_fail (DASOM_IS_IM (im), FALSE); GSocket *socket = g_socket_connection_get_socket (im->connection); if (!socket || g_socket_is_closed (socket)) { if (text) *text = g_strdup (""); if (cursor_index) *cursor_index = 0; g_warning ("socket is closed"); return FALSE; } dasom_send_message (socket, DASOM_MESSAGE_GET_SURROUNDING, NULL, 0, NULL); dasom_result_iteration_until (im->result, dasom_im_sockets_context, DASOM_MESSAGE_GET_SURROUNDING_REPLY); if (im->result->reply == NULL) { if (text) *text = g_strdup (""); if (cursor_index) *cursor_index = 0; return FALSE; } if (text) *text = g_strndup (im->result->reply->data, im->result->reply->header->data_len - 1 - sizeof (gint) - sizeof (gboolean)); if (cursor_index) { *cursor_index = *(gint *) (im->result->reply->data + im->result->reply->header->data_len - sizeof (gint) - sizeof (gboolean)); } return *(gboolean *) (im->result->reply->data - sizeof (gboolean)); }
void dasom_im_reset (DasomIM *im) { g_debug (G_STRLOC ": %s", G_STRFUNC); g_return_if_fail (DASOM_IS_IM (im)); GSocket *socket = g_socket_connection_get_socket (im->connection); if (!socket || g_socket_is_closed (socket)) { g_warning ("socket is closed"); return; } dasom_send_message (socket, DASOM_MESSAGE_RESET, NULL, 0, NULL); dasom_result_iteration_until (im->result, dasom_im_sockets_context, DASOM_MESSAGE_RESET_REPLY); }
void dasom_im_set_use_preedit (DasomIM *im, gboolean use_preedit) { g_debug (G_STRLOC ": %s", G_STRFUNC); g_return_if_fail (DASOM_IS_IM (im)); GSocket *socket = g_socket_connection_get_socket (im->connection); if (!socket || g_socket_is_closed (socket)) { g_warning ("socket is closed"); return; } dasom_send_message (socket, DASOM_MESSAGE_SET_USE_PREEDIT, (gchar *) &use_preedit, sizeof (gboolean), NULL); dasom_result_iteration_until (im->result, dasom_im_sockets_context, DASOM_MESSAGE_SET_USE_PREEDIT_REPLY); }
void dasom_im_set_cursor_location (DasomIM *im, const DasomRectangle *area) { g_debug (G_STRLOC ": %s", G_STRFUNC); g_return_if_fail (DASOM_IS_IM (im)); GSocket *socket = g_socket_connection_get_socket (im->connection); if (!socket || g_socket_is_closed (socket)) { g_warning ("socket is closed"); return; } dasom_send_message (socket, DASOM_MESSAGE_SET_CURSOR_LOCATION, (gchar *) area, sizeof (DasomRectangle), NULL); dasom_result_iteration_until (im->result, dasom_im_sockets_context, DASOM_MESSAGE_SET_CURSOR_LOCATION_REPLY); }
gboolean dasom_im_filter_event (DasomIM *im, DasomEvent *event) { g_debug (G_STRLOC ":%s", G_STRFUNC); g_return_val_if_fail (DASOM_IS_IM (im), FALSE); GSocket *socket = g_socket_connection_get_socket (im->connection); if (!socket || g_socket_is_closed (socket)) { g_warning ("socket is closed"); return dasom_im_filter_event_fallback (im, event); } dasom_send_message (socket, DASOM_MESSAGE_FILTER_EVENT, event, sizeof (DasomEvent), NULL); dasom_result_iteration_until (im->result, dasom_im_sockets_context, DASOM_MESSAGE_FILTER_EVENT_REPLY); if (im->result->reply == NULL) return dasom_im_filter_event_fallback (im, event); return *(gboolean *) (im->result->reply->data); }
void dasom_im_set_surrounding (DasomIM *im, const char *text, gint len, gint cursor_index) { g_debug (G_STRLOC ": %s", G_STRFUNC); g_return_if_fail (DASOM_IS_IM (im)); GSocket *socket = g_socket_connection_get_socket (im->connection); if (!socket || g_socket_is_closed (socket)) { g_warning ("socket is closed"); return; } gchar *data = NULL; gint str_len; if (len == -1) str_len = strlen (text); else str_len = len; data = g_strndup (text, str_len); data = g_realloc (data, str_len + 1 + 2 * sizeof (gint)); *(gint *) (data + str_len + 1) = len; *(gint *) (data + str_len + 1 + sizeof (gint)) = cursor_index; dasom_send_message (socket, DASOM_MESSAGE_SET_SURROUNDING, data, str_len + 1 + 2 * sizeof (gint), g_free); dasom_result_iteration_until (im->result, dasom_im_sockets_context, DASOM_MESSAGE_SET_SURROUNDING_REPLY); }
static gboolean on_incoming_message (GSocket *socket, GIOCondition condition, gpointer user_data) { g_debug (G_STRLOC ": %s: socket fd:%d", G_STRFUNC, g_socket_get_fd (socket)); DasomIM *im = DASOM_IM (user_data); dasom_message_unref (im->result->reply); im->result->is_dispatched = TRUE; if (condition & (G_IO_HUP | G_IO_ERR)) { /* Because two GSource is created over one socket, * when G_IO_HUP | G_IO_ERR, callback can run two times. * the following code avoid that callback runs two times. */ GSource *source = g_main_current_source (); if (source == im->default_context_source) g_source_destroy (im->sockets_context_source); else if (source == im->sockets_context_source) g_source_destroy (im->default_context_source); if (!g_socket_is_closed (socket)) g_socket_close (socket, NULL); im->result->reply = NULL; g_critical (G_STRLOC ": %s: G_IO_HUP | G_IO_ERR", G_STRFUNC); return G_SOURCE_REMOVE; } DasomMessage *message; message = dasom_recv_message (socket); im->result->reply = message; gboolean retval; if (G_UNLIKELY (message == NULL)) { g_critical (G_STRLOC ": NULL message"); return G_SOURCE_CONTINUE; } switch (message->header->type) { /* reply */ case DASOM_MESSAGE_FILTER_EVENT_REPLY: case DASOM_MESSAGE_RESET_REPLY: case DASOM_MESSAGE_FOCUS_IN_REPLY: case DASOM_MESSAGE_FOCUS_OUT_REPLY: case DASOM_MESSAGE_SET_SURROUNDING_REPLY: case DASOM_MESSAGE_GET_SURROUNDING_REPLY: case DASOM_MESSAGE_SET_CURSOR_LOCATION_REPLY: case DASOM_MESSAGE_SET_USE_PREEDIT_REPLY: break; /* signals */ case DASOM_MESSAGE_PREEDIT_START: g_signal_emit_by_name (im, "preedit-start"); dasom_send_message (socket, DASOM_MESSAGE_PREEDIT_START_REPLY, NULL, 0, NULL); break; case DASOM_MESSAGE_PREEDIT_END: g_signal_emit_by_name (im, "preedit-end"); dasom_send_message (socket, DASOM_MESSAGE_PREEDIT_END_REPLY, NULL, 0, NULL); break; case DASOM_MESSAGE_PREEDIT_CHANGED: g_free (im->preedit_string); im->preedit_string = g_strndup (message->data, message->header->data_len - 1 - sizeof (gint)); im->cursor_pos = *(gint *) (message->data + message->header->data_len - sizeof (gint)); g_signal_emit_by_name (im, "preedit-changed"); dasom_send_message (socket, DASOM_MESSAGE_PREEDIT_CHANGED_REPLY, NULL, 0, NULL); break; case DASOM_MESSAGE_COMMIT: dasom_message_ref (message); g_signal_emit_by_name (im, "commit", (const gchar *) message->data); dasom_message_unref (message); dasom_send_message (socket, DASOM_MESSAGE_COMMIT_REPLY, NULL, 0, NULL); break; case DASOM_MESSAGE_RETRIEVE_SURROUNDING: g_signal_emit_by_name (im, "retrieve-surrounding", &retval); dasom_send_message (socket, DASOM_MESSAGE_RETRIEVE_SURROUNDING_REPLY, &retval, sizeof (gboolean), NULL); break; case DASOM_MESSAGE_DELETE_SURROUNDING: dasom_message_ref (message); g_signal_emit_by_name (im, "delete-surrounding", ((gint *) message->data)[0], ((gint *) message->data)[1], &retval); dasom_message_unref (message); dasom_send_message (socket, DASOM_MESSAGE_DELETE_SURROUNDING_REPLY, &retval, sizeof (gboolean), NULL); break; default: g_warning (G_STRLOC ": %s: Unknown message type: %d", G_STRFUNC, message->header->type); break; } return G_SOURCE_CONTINUE; }
static void dasom_im_init (DasomIM *im) { g_debug (G_STRLOC ": %s", G_STRFUNC); GSocketClient *client; GSocketAddress *address; GSocket *socket; GError *error = NULL; address = g_unix_socket_address_new_with_type (DASOM_ADDRESS, -1, G_UNIX_SOCKET_ADDRESS_ABSTRACT); client = g_socket_client_new (); im->connection = g_socket_client_connect (client, G_SOCKET_CONNECTABLE (address), NULL, &error); g_object_unref (address); g_object_unref (client); if (im->connection == NULL) { g_critical (G_STRLOC ": %s: %s", G_STRFUNC, error->message); g_clear_error (&error); return; } socket = g_socket_connection_get_socket (im->connection); if (!socket) { g_critical (G_STRLOC ": %s: %s", G_STRFUNC, "Can't get socket"); return; } DasomMessage *message; DasomConnectionType type = DASOM_CONNECTION_DASOM_IM; dasom_send_message (socket, DASOM_MESSAGE_CONNECT, &type, sizeof (DasomConnectionType), NULL); g_socket_condition_wait (socket, G_IO_IN, NULL, NULL); message = dasom_recv_message (socket); if (G_UNLIKELY (message == NULL || message->header->type != DASOM_MESSAGE_CONNECT_REPLY)) { dasom_message_unref (message); g_error ("Couldn't connect to dasom daemon"); } dasom_message_unref (message); im->result = g_slice_new0 (DasomResult); im->preedit_string = g_strdup (""); GMutex mutex; g_mutex_init (&mutex); g_mutex_lock (&mutex); if (G_UNLIKELY (dasom_im_sockets_context == NULL)) { dasom_im_sockets_context = g_main_context_new (); dasom_im_sockets_context_ref_count++; } else { dasom_im_sockets_context = g_main_context_ref (dasom_im_sockets_context); dasom_im_sockets_context_ref_count++; } g_mutex_unlock (&mutex); /* when g_main_context_iteration(), iterate only sockets */ im->sockets_context_source = g_socket_create_source (socket, G_IO_IN, NULL); g_source_set_can_recurse (im->sockets_context_source, TRUE); g_source_attach (im->sockets_context_source, dasom_im_sockets_context); g_source_set_callback (im->sockets_context_source, (GSourceFunc) on_incoming_message, im, NULL); im->default_context_source = g_socket_create_source (socket, G_IO_IN, NULL); g_source_set_can_recurse (im->default_context_source, TRUE); g_source_set_callback (im->default_context_source, (GSourceFunc) on_incoming_message, im, NULL); g_source_attach (im->default_context_source, NULL); }
static gboolean on_incoming_message_dasom (GSocket *socket, GIOCondition condition, DasomConnection *connection) { g_debug (G_STRLOC ": %s", G_STRFUNC); DasomMessage *message; gboolean retval; if (condition & (G_IO_HUP | G_IO_ERR)) { g_debug (G_STRLOC ": condition & (G_IO_HUP | G_IO_ERR)"); g_socket_close (socket, NULL); dasom_message_unref (connection->reply); connection->reply = NULL; if (G_UNLIKELY (connection->type == DASOM_CONNECTION_DASOM_AGENT)) connection->server->agents_list = g_list_remove (connection->server->agents_list, connection); g_hash_table_remove (connection->server->connections, GUINT_TO_POINTER (dasom_connection_get_id (connection))); return G_SOURCE_REMOVE; } if (connection->type == DASOM_CONNECTION_DASOM_IM) dasom_engine_set_english_mode (connection->engine, connection->is_english_mode); message = dasom_recv_message (socket); dasom_message_unref (connection->reply); connection->reply = message; connection->is_dispatched = TRUE; switch (message->header->type) { case DASOM_MESSAGE_FILTER_EVENT: dasom_message_ref (message); retval = dasom_connection_filter_event (connection, (DasomEvent *) message->data); dasom_message_unref (message); dasom_send_message (socket, DASOM_MESSAGE_FILTER_EVENT_REPLY, &retval, sizeof (gboolean), NULL); break; case DASOM_MESSAGE_GET_PREEDIT_STRING: { gchar *data = NULL; gint cursor_pos; gint str_len = 0; dasom_connection_get_preedit_string (connection, &data, &cursor_pos); str_len = strlen (data); data = g_realloc (data, str_len + 1 + sizeof (gint)); *(gint *) (data + str_len + 1) = cursor_pos; dasom_send_message (socket, DASOM_MESSAGE_GET_PREEDIT_STRING_REPLY, data, str_len + 1 + sizeof (gint), NULL); g_free (data); } break; case DASOM_MESSAGE_RESET: dasom_connection_reset (connection); dasom_send_message (socket, DASOM_MESSAGE_RESET_REPLY, NULL, 0, NULL); break; case DASOM_MESSAGE_FOCUS_IN: dasom_connection_focus_in (connection); dasom_send_message (socket, DASOM_MESSAGE_FOCUS_IN_REPLY, NULL, 0, NULL); break; case DASOM_MESSAGE_FOCUS_OUT: dasom_connection_focus_out (connection); dasom_send_message (socket, DASOM_MESSAGE_FOCUS_OUT_REPLY, NULL, 0, NULL); break; case DASOM_MESSAGE_SET_SURROUNDING: { dasom_message_ref (message); gchar *data = message->data; guint16 data_len = message->header->data_len; gint str_len = data_len - 1 - 2 * sizeof (gint); gint cursor_index = *(gint *) (data + data_len - sizeof (gint)); dasom_connection_set_surrounding (connection, data, str_len, cursor_index); dasom_message_unref (message); dasom_send_message (socket, DASOM_MESSAGE_SET_SURROUNDING_REPLY, NULL, 0, NULL); } break; case DASOM_MESSAGE_GET_SURROUNDING: { gchar *data; gint cursor_index; gint str_len = 0; retval = dasom_connection_get_surrounding (connection, &data, &cursor_index); str_len = strlen (data); data = g_realloc (data, str_len + 1 + sizeof (gint) + sizeof (gboolean)); *(gint *) (data + str_len + 1) = cursor_index; *(gboolean *) (data + str_len + 1 + sizeof (gint)) = retval; dasom_send_message (socket, DASOM_MESSAGE_GET_SURROUNDING_REPLY, data, str_len + 1 + sizeof (gint) + sizeof (gboolean), NULL); g_free (data); } break; case DASOM_MESSAGE_SET_CURSOR_LOCATION: dasom_message_ref (message); dasom_connection_set_cursor_location (connection, (DasomRectangle *) message->data); dasom_message_unref (message); dasom_send_message (socket, DASOM_MESSAGE_SET_CURSOR_LOCATION_REPLY, NULL, 0, NULL); break; case DASOM_MESSAGE_SET_USE_PREEDIT: dasom_message_ref (message); dasom_connection_set_use_preedit (connection, *(gboolean *) message->data); dasom_message_unref (message); dasom_send_message (socket, DASOM_MESSAGE_SET_USE_PREEDIT_REPLY, NULL, 0, NULL); break; case DASOM_MESSAGE_PREEDIT_START_REPLY: case DASOM_MESSAGE_PREEDIT_CHANGED_REPLY: case DASOM_MESSAGE_PREEDIT_END_REPLY: case DASOM_MESSAGE_COMMIT_REPLY: case DASOM_MESSAGE_RETRIEVE_SURROUNDING_REPLY: case DASOM_MESSAGE_DELETE_SURROUNDING_REPLY: break; default: g_warning ("Unknown message type: %d", message->header->type); break; } if (connection->type == DASOM_CONNECTION_DASOM_IM) connection->is_english_mode = dasom_engine_get_english_mode (connection->engine); return G_SOURCE_CONTINUE; }