summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--configure.ac9
-rw-r--r--include/rofi-i3.h32
-rw-r--r--include/rofi.h10
-rw-r--r--source/rofi-i3.c154
-rw-r--r--source/rofi.c190
6 files changed, 239 insertions, 158 deletions
diff --git a/Makefile.am b/Makefile.am
index a55dd526..94e8b712 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -23,6 +23,7 @@ AM_CFLAGS=\
rofi_SOURCES=\
source/rofi.c\
+ source/rofi-i3.c\
source/textbox.c\
source/xrmoptions.c\
source/dmenu-dialog.c\
@@ -33,6 +34,7 @@ rofi_SOURCES=\
config/config.c\
source/helper.c\
include/rofi.h\
+ include/rofi-i3.h\
include/run-dialog.h\
include/ssh-dialog.h\
include/dmenu-dialog.h\
diff --git a/configure.ac b/configure.ac
index 9c87ce22..605cf875 100644
--- a/configure.ac
+++ b/configure.ac
@@ -21,8 +21,13 @@ AC_USE_SYSTEM_EXTENSIONS
##
# I3 check
##
-AC_CHECK_HEADERS([i3/ipc.h],
- [i3_header=yes; break;])
+AC_ARG_ENABLE(i3support,
+ [AS_HELP_STRING([--disable-i3support], [Disable check for i3 support])])
+if test "x$enable_i3support" != xno;
+then
+ AC_CHECK_HEADERS([i3/ipc.h],
+ [i3_header=yes; break;])
+fi
dnl ---------------------------------------------------------------------
diff --git a/include/rofi-i3.h b/include/rofi-i3.h
new file mode 100644
index 00000000..4187fc26
--- /dev/null
+++ b/include/rofi-i3.h
@@ -0,0 +1,32 @@
+#ifndef __ROFI_I3_H__
+#define __ROFI_I3_H__
+
+/**
+ * These functions are dummies when i3 support is not compiled in.
+ */
+
+/**
+ * @param socket_path The I3 IPC socket.
+ * @param id The window to focus on.
+ *
+ * If we want to switch windows in I3, we use I3 IPC mode.
+ * This works more better then sending messages via X11.
+ * Hopefully at some point, I3 gets fixed and this is not needed.
+ * This function takes the path to the i3 IPC socket, and the XID of the window.
+ */
+void i3_support_focus_window ( Window id );
+
+/**
+ * @param display The display to read the i3 property from.
+ *
+ * Get the i3 socket from the X root window.
+ * @returns TRUE when i3 is running, FALSE when not.
+ */
+
+int i3_support_initialize ( Display *display );
+
+/**
+ * Cleanup.
+ */
+void i3_support_free_internals ( void );
+#endif // __ROFI_I3_H__
diff --git a/include/rofi.h b/include/rofi.h
index e9eb5396..49cc4305 100644
--- a/include/rofi.h
+++ b/include/rofi.h
@@ -219,4 +219,14 @@ extern Settings config;
*/
void error_dialog ( char *msg );
+/**
+ * @param w The Window to read property from.
+ * @param atom The property identifier
+ *
+ * Get text property defined by atom from window.
+ * Support utf8.
+ *
+ * @returns a newly allocated string with the result or NULL
+ */
+char* window_get_text_prop ( Window w, Atom atom );
#endif
diff --git a/source/rofi-i3.c b/source/rofi-i3.c
new file mode 100644
index 00000000..f853338d
--- /dev/null
+++ b/source/rofi-i3.c
@@ -0,0 +1,154 @@
+/**
+ * rofi
+ *
+ * MIT/X11 License
+ * Copyright (c) 2013-2014 Qball Cow <qball@gmpclient.org>
+ *
+ * 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 <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <time.h>
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <sys/socket.h>
+#include <linux/un.h>
+
+#include "rofi.h"
+#include "rofi-i3.h"
+
+#ifdef HAVE_I3_IPC_H
+#include <i3/ipc.h>
+// Path to HAVE_I3_IPC_H socket.
+char *i3_socket_path = NULL;
+
+void i3_support_focus_window ( Window id )
+{
+ i3_ipc_header_t head;
+ char command[128];
+ int s, len;
+ ssize_t t;
+ struct sockaddr_un remote;
+
+ if ( strlen ( i3_socket_path ) > UNIX_PATH_MAX ) {
+ fprintf ( stderr, "Socket path is to long. %zd > %d\n", strlen ( i3_socket_path ), UNIX_PATH_MAX );
+ 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;
+ strcpy ( remote.sun_path, i3_socket_path );
+ len = strlen ( remote.sun_path ) + sizeof ( remote.sun_family );
+
+ if ( connect ( s, ( struct sockaddr * ) &remote, len ) == -1 ) {
+ fprintf ( stderr, "Failed to connect to I3 (%s): %s\n", i3_socket_path, strerror ( errno ) );
+ close ( s );
+ return;
+ }
+
+
+ // Formulate command
+ snprintf ( command, 128, "[id=\"%lu\"] 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 ) );
+ error_dialog ( msg );
+ 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 ) );
+ error_dialog ( msg );
+ 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 ( Display *display )
+{
+ Atom i3_sp_atom = XInternAtom ( display, "I3_SOCKET_PATH", False );
+
+ if ( i3_sp_atom != None ) {
+ // Get the default screen.
+ Screen *screen = DefaultScreenOfDisplay ( display );
+ // Find the root window (each X has one.).
+ Window root = RootWindow ( display, XScreenNumberOfScreen ( screen ) );
+ // Get the i3 path property.
+ i3_socket_path = window_get_text_prop ( root, i3_sp_atom );
+ }
+ // If we find it, go into i3 mode.
+ return ( i3_socket_path != NULL ) ? TRUE : FALSE;
+}
+
+void i3_support_free_internals ( void )
+{
+ if ( i3_socket_path != NULL ) {
+ g_free ( i3_socket_path );
+ }
+}
+
+#else
+
+
+void i3_support_focus_window ( Window 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 ( Display *display )
+{
+ return FALSE;
+}
+#endif // HAVE_I3_IPC_H
diff --git a/source/rofi.c b/source/rofi.c
index 738a1764..79931d7e 100644
--- a/source/rofi.c
+++ b/source/rofi.c
@@ -49,14 +49,10 @@
#include <sys/file.h>
#include <sys/types.h>
-#ifdef HAVE_I3_IPC_H
-#include <sys/socket.h>
-#include <linux/un.h>
-#include <i3/ipc.h>
-#endif
#include "helper.h"
#include "rofi.h"
+#include "rofi-i3.h"
#include "run-dialog.h"
#include "ssh-dialog.h"
@@ -68,12 +64,8 @@
#define LINE_MARGIN 3
-#ifdef HAVE_I3_IPC_H
// This setting is no longer user configurable, but partial to this file:
int config_i3_mode = 0;
-// Path to HAVE_I3_IPC_H socket.
-char *i3_socket_path = NULL;
-#endif
char *pidfile = NULL;
static void create_pid_file ( const char *pidfile );
@@ -99,7 +91,6 @@ static int ( *xerror )( Display *, XErrorEvent * );
X ( _NET_WM_STATE_SKIP_PAGER ), \
X ( _NET_WM_STATE_ABOVE ), \
X ( _NET_WM_DESKTOP ), \
- X ( I3_SOCKET_PATH ), \
X ( CLIPBOARD ), \
X ( UTF8_STRING ), \
X ( _NET_WM_WINDOW_OPACITY )
@@ -151,82 +142,6 @@ static int switcher_get ( const char *name )
}
-#ifdef HAVE_I3_IPC_H
-/**
- * @param socket_path The I3 IPC socket.
- * @param id The window to focus on.
- *
- * If we want to switch windows in I3, we use I3 IPC mode.
- * This works more better then sending messages via X11.
- * Hopefully at some point, I3 gets fixed and this is not needed.
- * This function takes the path to the i3 IPC socket, and the XID of the window.
- */
-static void focus_window_i3 ( const char *socket_path, Window id )
-{
- i3_ipc_header_t head;
- char command[128];
- int s, len;
- ssize_t t;
- struct sockaddr_un remote;
-
- if ( strlen ( socket_path ) > UNIX_PATH_MAX ) {
- fprintf ( stderr, "Socket path is to long. %zd > %d\n", strlen ( socket_path ), UNIX_PATH_MAX );
- 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;
- strcpy ( remote.sun_path, socket_path );
- len = strlen ( remote.sun_path ) + sizeof ( remote.sun_family );
-
- if ( connect ( s, ( struct sockaddr * ) &remote, len ) == -1 ) {
- fprintf ( stderr, "Failed to connect to I3 (%s): %s\n", socket_path, strerror ( errno ) );
- close ( s );
- return;
- }
-
-
- // Formulate command
- snprintf ( command, 128, "[id=\"%lu\"] 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 ) );
- error_dialog ( msg );
- 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 ) );
- error_dialog ( msg );
- 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 );
-}
-#endif
void catch_exit ( __attribute__( ( unused ) ) int sig )
{
@@ -578,7 +493,7 @@ static int window_get_prop ( Window w, Atom prop, Atom *type, int *items, void *
// retrieve a text property from a window
// technically we could use window_get_prop(), but this is better for character set support
-static char* window_get_text_prop ( Window w, Atom atom )
+char* window_get_text_prop ( Window w, Atom atom )
{
XTextProperty prop;
char *res = NULL;
@@ -2092,14 +2007,11 @@ SwitcherMode run_switcher_window ( char **input, G_GNUC_UNUSED void *data )
&& !client_has_state ( c, netatoms[_NET_WM_STATE_SKIP_TASKBAR] ) ) {
classfield = MAX ( classfield, strlen ( c->class ) );
-#ifdef HAVE_I3_IPC_H
-
// In i3 mode, skip the i3bar completely.
if ( config_i3_mode && strstr ( c->class, "i3bar" ) != NULL ) {
continue;
}
-#endif
if ( c->window == curr_win_id ) {
c->active = TRUE;
}
@@ -2111,18 +2023,14 @@ SwitcherMode run_switcher_window ( char **input, G_GNUC_UNUSED void *data )
if ( !window_get_cardinal_prop ( root, netatoms[_NET_NUMBER_OF_DESKTOPS], &desktops, 1 ) ) {
desktops = 1;
}
-#ifdef HAVE_I3_IPC_H
if ( config_i3_mode ) {
sprintf ( pattern, "%%-%ds %%s", MAX ( 5, classfield ) );
}
else{
-#endif
- sprintf ( pattern, "%%-%ds %%-%ds %%s", desktops < 10 ? 1 : 2, MAX ( 5, classfield ) );
-#ifdef HAVE_I3_IPC_H
- }
-#endif
- char **list = g_malloc0_n ( ( ids->len + 1 ), sizeof ( char* ) );
- unsigned int lines = 0;
+ sprintf ( pattern, "%%-%ds %%-%ds %%s", desktops < 10 ? 1 : 2, MAX ( 5, classfield ) );
+ }
+ char **list = g_malloc0_n ( ( ids->len + 1 ), sizeof ( char* ) );
+ unsigned int lines = 0;
// build the actual list
for ( i = 0; i < ( ids->len ); i++ ) {
@@ -2135,34 +2043,30 @@ SwitcherMode run_switcher_window ( char **input, G_GNUC_UNUSED void *data )
char desktop[5];
desktop[0] = 0;
char *line = g_malloc ( strlen ( c->title ) + strlen ( c->class ) + classfield + 50 );
-#ifdef HAVE_I3_IPC_H
if ( !config_i3_mode ) {
-#endif
- // find client's desktop. this is zero-based, so we adjust by since most
- // normal people don't think like this :-)
- if ( !window_get_cardinal_prop ( c->window, netatoms[_NET_WM_DESKTOP], &wmdesktop, 1 ) ) {
- wmdesktop = 0xFFFFFFFF;
- }
+ // find client's desktop. this is zero-based, so we adjust by since most
+ // normal people don't think like this :-)
+ if ( !window_get_cardinal_prop ( c->window, netatoms[_NET_WM_DESKTOP], &wmdesktop, 1 ) ) {
+ wmdesktop = 0xFFFFFFFF;
+ }
- if ( wmdesktop < 0xFFFFFFFF ) {
- sprintf ( desktop, "%d", (int) wmdesktop + 1 );
- }
+ if ( wmdesktop < 0xFFFFFFFF ) {
+ sprintf ( desktop, "%d", (int) wmdesktop + 1 );
+ }
- sprintf ( line, pattern, desktop, c->class, c->title );
-#ifdef HAVE_I3_IPC_H
- }
- else{
- sprintf ( line, pattern, c->class, c->title );
- }
-#endif
+ sprintf ( line, pattern, desktop, c->class, c->title );
+ }
+ else{
+ sprintf ( line, pattern, c->class, c->title );
+ }
list[lines++] = line;
}
}
- Time time;
- int selected_line = 0;
- MenuReturn mretv = menu ( list, lines, input, "window:", &time, NULL,
- window_match, ids, &selected_line, config.levenshtein_sort );
+ Time time;
+ int selected_line = 0;
+ MenuReturn mretv = menu ( list, lines, input, "window:", &time, NULL,
+ window_match, ids, &selected_line, config.levenshtein_sort );
if ( mretv == MENU_NEXT ) {
retv = NEXT_DIALOG;
@@ -2174,15 +2078,11 @@ SwitcherMode run_switcher_window ( char **input, G_GNUC_UNUSED void *data )
retv = selected_line;
}
else if ( ( mretv == MENU_OK || mretv == MENU_CUSTOM_INPUT ) && list[selected_line] ) {
-#ifdef HAVE_I3_IPC_H
-
if ( config_i3_mode ) {
// Hack for i3.
- focus_window_i3 ( i3_socket_path, ids->array[selected_line] );
+ i3_support_focus_window ( ids->array[selected_line] );
}
- else
-#endif
- {
+ else{
// Change to the desktop of the selected window/client.
// TODO: get rid of strtol
window_send_message ( root, root, netatoms[_NET_CURRENT_DESKTOP], strtol ( list[selected_line], NULL, 10 ) - 1,
@@ -2399,8 +2299,8 @@ static void parse_key ( char *combo, unsigned int *mod, KeySym *key )
// bind a key combination on a root window, compensating for Lock* states
static void grab_key ( Display *display, unsigned int modmask, KeySym key )
{
- Screen *screen = DefaultScreenOfDisplay ( display );
- Window root = RootWindow ( display, XScreenNumberOfScreen ( screen ) );
+ Screen *screen = DefaultScreenOfDisplay ( display );
+ Window root = RootWindow ( display, XScreenNumberOfScreen ( screen ) );
KeyCode keycode = XKeysymToKeycode ( display, key );
XUngrabKey ( display, keycode, AnyModifier, root );
@@ -2421,22 +2321,6 @@ static void grab_key ( Display *display, unsigned int modmask, KeySym key )
}
-#ifdef HAVE_I3_IPC_H
-/**
- * Get the i3 socket from the X root window.
- */
-static inline void display_get_i3_path ( Display *display )
-{
- // Get the default screen.
- Screen *screen = DefaultScreenOfDisplay ( display );
- // Find the root window (each X has one.).
- Window root = RootWindow ( display, XScreenNumberOfScreen ( screen ) );
- // Get the i3 path property.
- i3_socket_path = window_get_text_prop ( root, netatoms[I3_SOCKET_PATH] );
- // If we find it, go into i3 mode.
- config_i3_mode = ( i3_socket_path != NULL ) ? TRUE : FALSE;
-}
-#endif //HAVE_I3_IPC_H
/**
@@ -2559,13 +2443,9 @@ static void cleanup ()
if ( cache_client != NULL ) {
winlist_free ( cache_client );
}
-#ifdef HAVE_I3_IPC_H
- if ( i3_socket_path != NULL ) {
- g_free ( i3_socket_path );
- }
+ i3_support_free_internals ();
-#endif
// Cleaning up memory allocated by the Xresources file.
// TODO, not happy with this.
@@ -2689,7 +2569,7 @@ static void setup_switchers ( void )
/**
* Keep a copy of arc, argv around, so we can use the same parsing method
*/
-static int stored_argc;
+static int stored_argc;
static char **stored_argv;
/**
@@ -2758,9 +2638,9 @@ static void create_pid_file ( const char *pidfile )
}
if ( ftruncate ( fd, (off_t) 0 ) == 0 ) {
// Write pid, not needed, but for completeness sake.
- char buffer[64];
- int length = snprintf ( buffer, 64, "%i", getpid () );
- ssize_t l = 0;
+ char buffer[64];
+ int length = snprintf ( buffer, 64, "%i", getpid () );
+ ssize_t l = 0;
while ( l < length ) {
l += write ( fd, &buffer[l], length - l );
}
@@ -2816,7 +2696,7 @@ int main ( int argc, char *argv[] )
// determine numlock mask so we can bind on keys with and without it
XModifierKeymap *modmap = XGetModifierMapping ( display );
- KeyCode kc = XKeysymToKeycode ( display, XK_Num_Lock );
+ KeyCode kc = XKeysymToKeycode ( display, XK_Num_Lock );
for ( int i = 0; i < 8; i++ ) {
for ( int j = 0; j < ( int ) modmap->max_keypermod; j++ ) {
if ( modmap->modifiermap[i * modmap->max_keypermod + j] == kc ) {
@@ -2834,10 +2714,8 @@ int main ( int argc, char *argv[] )
netatoms[i] = XInternAtom ( display, netatom_names[i], False );
}
-#ifdef HAVE_I3_IPC_H
// Check for i3
- display_get_i3_path ( display );
-#endif
+ config_i3_mode = i3_support_initialize ( display );
char *msg = NULL;
if ( find_arg_str ( argc, argv, "-e", &( msg ) ) ) {