/** * rofi * * MIT/X11 License * Copyright (c) 2013-2016 Qball Cow * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include "xcb.h" #include "rofi.h" #include "x11-helper.h" #include "i3-support.h" #include "view.h" #ifdef HAVE_I3_IPC_H #include // Path to HAVE_I3_IPC_H socket. char *i3_socket_path = NULL; void i3_support_focus_window ( xcb_window_t id ) { i3_ipc_header_t head; int s; ssize_t t; struct sockaddr_un remote; size_t upm = sizeof ( remote.sun_path ); char command[upm]; if ( strlen ( i3_socket_path ) > upm ) { fprintf ( stderr, "Socket path is too long. %zu > %zu\n", strlen ( i3_socket_path ), upm ); return; } if ( ( s = socket ( AF_UNIX, SOCK_STREAM, 0 ) ) == -1 ) { fprintf ( stderr, "Failed to open connection to I3: %s\n", strerror ( errno ) ); return; } remote.sun_family = AF_UNIX; g_strlcpy ( remote.sun_path, i3_socket_path, upm ); if ( connect ( s, ( struct sockaddr * ) &remote, sizeof ( struct sockaddr_un ) ) == -1 ) { fprintf ( stderr, "Failed to connect to I3 (%s): %s\n", i3_socket_path, strerror ( errno ) ); close ( s ); return; } // Formulate command snprintf ( command, upm, "[id=\"%u\"] focus", id ); // Prepare header. memcpy ( head.magic, I3_IPC_MAGIC, 6 ); head.size = strlen ( command ); head.type = I3_IPC_MESSAGE_TYPE_COMMAND; // Send header. t = send ( s, &head, sizeof ( i3_ipc_header_t ), 0 ); if ( t == -1 ) { char *msg = g_strdup_printf ( "Failed to send message header to i3: %s\n", strerror ( errno ) ); rofi_view_error_dialog ( msg, FALSE ); g_free ( msg ); close ( s ); return; } // Send message t = send ( s, command, strlen ( command ), 0 ); if ( t == -1 ) { char *msg = g_strdup_printf ( "Failed to send message body to i3: %s\n", strerror ( errno ) ); rofi_view_error_dialog ( msg, FALSE ); g_free ( msg ); close ( s ); return; } // Receive header. t = recv ( s, &head, sizeof ( head ), 0 ); if ( t == sizeof ( head ) ) { t = recv ( s, command, head.size, 0 ); if ( t == head.size ) { // Response. } } close ( s ); } int i3_support_initialize ( xcb_stuff *xcb ) { // If we where initialized, clean this first. i3_support_free_internals (); // Get atom for I3_SOCKET_PATH i3_socket_path = window_get_text_prop ( xcb_stuff_get_root_window ( xcb ), netatoms[I3_SOCKET_PATH] ); // If we find it, go into i3 mode. return ( i3_socket_path != NULL ) ? TRUE : FALSE; } void i3_support_free_internals ( void ) { g_free ( i3_socket_path ); i3_socket_path = NULL; } #else void i3_support_focus_window ( G_GNUC_UNUSED xcb_window_t id ) { fprintf ( stderr, "Trying to control i3, when i3 support is not enabled.\n" ); abort (); } void i3_support_free_internals ( void ) { } int i3_support_initialize ( G_GNUC_UNUSED xcb_stuff *xcb ) { return FALSE; } #endif // HAVE_I3_IPC_H