src/core/linux/SDL_dbus.c
author Alex Baines <alex@abaines.me.uk>
Wed, 18 Jun 2014 20:11:39 +0100
changeset 8889 26a6243b27c2
child 8977 84ae33058c67
permissions -rw-r--r--
Add IBus IME Support, move DBus code to its own file. (v3.3 squashed)
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "../../SDL_internal.h"
    22 #include "SDL_dbus.h"
    23 
    24 #if SDL_USE_LIBDBUS
    25 /* we never link directly to libdbus. */
    26 #include "SDL_loadso.h"
    27 static const char *dbus_library = "libdbus-1.so.3";
    28 static void *dbus_handle = NULL;
    29 static unsigned int screensaver_cookie = 0;
    30 static SDL_DBusContext dbus = {0};
    31 
    32 static int
    33 load_dbus_syms(void)
    34 {
    35     #define SDL_DBUS_SYM2(x, y) \
    36         if (!(dbus.x = SDL_LoadFunction(dbus_handle, #y))) return -1
    37         
    38     #define SDL_DBUS_SYM(x) \
    39         SDL_DBUS_SYM2(x, dbus_##x)
    40 
    41     SDL_DBUS_SYM(bus_get_private);
    42     SDL_DBUS_SYM(bus_register);
    43     SDL_DBUS_SYM(bus_add_match);
    44     SDL_DBUS_SYM(connection_open_private);
    45     SDL_DBUS_SYM(connection_set_exit_on_disconnect);
    46     SDL_DBUS_SYM(connection_get_is_connected);
    47     SDL_DBUS_SYM(connection_add_filter);
    48     SDL_DBUS_SYM(connection_send);
    49     SDL_DBUS_SYM(connection_send_with_reply_and_block);
    50     SDL_DBUS_SYM(connection_close);
    51     SDL_DBUS_SYM(connection_unref);
    52     SDL_DBUS_SYM(connection_flush);
    53     SDL_DBUS_SYM(connection_read_write);
    54     SDL_DBUS_SYM(connection_dispatch);
    55     SDL_DBUS_SYM(message_is_signal);
    56     SDL_DBUS_SYM(message_new_method_call);
    57     SDL_DBUS_SYM(message_append_args);
    58     SDL_DBUS_SYM(message_get_args);
    59     SDL_DBUS_SYM(message_iter_init);
    60     SDL_DBUS_SYM(message_iter_next);
    61     SDL_DBUS_SYM(message_iter_get_basic);
    62     SDL_DBUS_SYM(message_iter_get_arg_type);
    63     SDL_DBUS_SYM(message_iter_recurse);
    64     SDL_DBUS_SYM(message_unref);
    65     SDL_DBUS_SYM(error_init);
    66     SDL_DBUS_SYM(error_is_set);
    67     SDL_DBUS_SYM(error_free);
    68     SDL_DBUS_SYM(get_local_machine_id);
    69     SDL_DBUS_SYM(free);
    70 
    71     #undef SDL_DBUS_SYM
    72     #undef SDL_DBUS_SYM2
    73 
    74     return 0;
    75 }
    76 
    77 static void
    78 UnloadDBUSLibrary(void)
    79 {
    80     if (dbus_handle != NULL) {
    81         SDL_UnloadObject(dbus_handle);
    82         dbus_handle = NULL;
    83     }
    84 }
    85 
    86 static int
    87 LoadDBUSLibrary(void)
    88 {
    89     int retval = 0;
    90     if (dbus_handle == NULL) {
    91         dbus_handle = SDL_LoadObject(dbus_library);
    92         if (dbus_handle == NULL) {
    93             retval = -1;
    94             /* Don't call SDL_SetError(): SDL_LoadObject already did. */
    95         } else {
    96             retval = load_dbus_syms();
    97             if (retval < 0) {
    98                 UnloadDBUSLibrary();
    99             }
   100         }
   101     }
   102 
   103     return retval;
   104 }
   105 
   106 void
   107 SDL_DBus_Init(void)
   108 {
   109     if (LoadDBUSLibrary() != -1) {
   110         DBusError err;
   111         dbus.error_init(&err);
   112         dbus.session_conn = dbus.bus_get_private(DBUS_BUS_SESSION, &err);
   113         if (dbus.error_is_set(&err)) {
   114             dbus.error_free(&err);
   115             if (dbus.session_conn) {
   116                 dbus.connection_unref(dbus.session_conn);
   117                 dbus.session_conn = NULL;
   118             }
   119             return;  /* oh well */
   120         }
   121         dbus.connection_set_exit_on_disconnect(dbus.session_conn, 0);
   122     }
   123 }
   124 
   125 void
   126 SDL_DBus_Quit(void)
   127 {
   128     if (dbus.session_conn) {
   129         dbus.connection_close(dbus.session_conn);
   130         dbus.connection_unref(dbus.session_conn);
   131         SDL_memset(&dbus, 0, sizeof(dbus));
   132     }
   133     UnloadDBUSLibrary();
   134 }
   135 
   136 SDL_DBusContext *
   137 SDL_DBus_GetContext(void)
   138 {
   139     if(!dbus_handle || !dbus.session_conn){
   140         SDL_DBus_Init();
   141     }
   142     
   143     if(dbus_handle && dbus.session_conn){
   144         return &dbus;
   145     } else {
   146         return NULL;
   147     }
   148 }
   149 
   150 void
   151 SDL_DBus_ScreensaverTickle(void)
   152 {
   153     DBusConnection *conn = dbus.session_conn;
   154     if (conn != NULL) {
   155         DBusMessage *msg = dbus.message_new_method_call("org.gnome.ScreenSaver",
   156                                                         "/org/gnome/ScreenSaver",
   157                                                         "org.gnome.ScreenSaver",
   158                                                         "SimulateUserActivity");
   159         if (msg != NULL) {
   160             if (dbus.connection_send(conn, msg, NULL)) {
   161                 dbus.connection_flush(conn);
   162             }
   163             dbus.message_unref(msg);
   164         }
   165     }
   166 }
   167 
   168 SDL_bool
   169 SDL_DBus_ScreensaverInhibit(SDL_bool inhibit)
   170 {
   171     DBusConnection *conn = dbus.session_conn;
   172 
   173     if (conn == NULL)
   174         return SDL_FALSE;
   175 
   176     if (inhibit &&
   177         screensaver_cookie != 0)
   178         return SDL_TRUE;
   179     if (!inhibit &&
   180         screensaver_cookie == 0)
   181         return SDL_TRUE;
   182 
   183     if (inhibit) {
   184         const char *app = "My SDL application";
   185         const char *reason = "Playing a game";
   186 
   187         DBusMessage *msg = dbus.message_new_method_call("org.freedesktop.ScreenSaver",
   188                                                          "/org/freedesktop/ScreenSaver",
   189                                                          "org.freedesktop.ScreenSaver",
   190                                                          "Inhibit");
   191         if (msg != NULL) {
   192             dbus.message_append_args (msg,
   193                                       DBUS_TYPE_STRING, &app,
   194                                       DBUS_TYPE_STRING, &reason,
   195                                       DBUS_TYPE_INVALID);
   196         }
   197 
   198         if (msg != NULL) {
   199             DBusMessage *reply;
   200 
   201             reply = dbus.connection_send_with_reply_and_block(conn, msg, 300, NULL);
   202             if (reply) {
   203                 if (!dbus.message_get_args(reply, NULL,
   204                                            DBUS_TYPE_UINT32, &screensaver_cookie,
   205                                            DBUS_TYPE_INVALID))
   206                     screensaver_cookie = 0;
   207                 dbus.message_unref(reply);
   208             }
   209 
   210             dbus.message_unref(msg);
   211         }
   212 
   213         if (screensaver_cookie == 0) {
   214             return SDL_FALSE;
   215         }
   216         return SDL_TRUE;
   217     } else {
   218         DBusMessage *msg = dbus.message_new_method_call("org.freedesktop.ScreenSaver",
   219                                                         "/org/freedesktop/ScreenSaver",
   220                                                         "org.freedesktop.ScreenSaver",
   221                                                         "UnInhibit");
   222         dbus.message_append_args (msg,
   223                                   DBUS_TYPE_UINT32, &screensaver_cookie,
   224                                   DBUS_TYPE_INVALID);
   225         if (msg != NULL) {
   226             if (dbus.connection_send(conn, msg, NULL)) {
   227                 dbus.connection_flush(conn);
   228             }
   229             dbus.message_unref(msg);
   230         }
   231 
   232         screensaver_cookie = 0;
   233         return SDL_TRUE;
   234     }
   235 }
   236 #endif