Index: openbox/actions/remember.c =================================================================== --- openbox/actions/remember.c (.../3.4.10) (revision 0) +++ openbox/actions/remember.c (.../3.4.10-dr) (revision 42) @@ -0,0 +1,170 @@ + +#include "openbox/actions.h" +#include "openbox/client.h" +#include "openbox/screen.h" +#include "openbox/frame.h" +#include "openbox/popup.h" +#include "openbox/mainloop.h" +#include "openbox/openbox.h" +#include +#include + +/* +OpenBox actions to remember/recall windows as a hotkey action + +Daniel Ramsay 2009-12-29 + +2010-01-19: Added desktop switch, updated to build against 3.4.10 +2010-01-31: Added visual feedback to the remember action + +Usage info: + +Configure a keybinding in rc.xml to execute the "Remember" action. + + + F5 + + +Remember requires one parameter, "id". +This id parameter is currently not used. + +When a configured "remember" keybind action is invoked, the remember action will save the currently focussed +window's XID against that key. + +Subsequently invoking the keybinding will activate the stored client, switching to the client's desktop if +required. + +If a remembered window has been closed/deleted in the meantime, the stored XID is overwritten and the +hotkey can be reassigned to a new window. + +A future version will include a separate action to clear hotkey->window assignments, and separate +actions to remember and recall windows for a given slot "id" (which is what the ID parameter will be for). + +*/ + +static gpointer remember_setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node); +static void remember_free_func(gpointer options); +static gboolean remember_run_func(ObActionsData *data, gpointer options); +static ObPopup *remember_popup = NULL; +static gboolean remember_popup_timeout(gpointer data); + +/* +Simple options struct retains the ID value and the selected window ID for the +keybinding. +*/ + +typedef struct { + + gchar *id; /* The hotkey ID value */ + Window xid; /* The stored Window ID, or -1 if none */ +} Options; + +/* +Action module entrypoint +*/ + +void action_remember_startup(void) +{ + actions_register("Remember", + remember_setup_func, + remember_free_func, + remember_run_func, + NULL, NULL); +} + +/* +Setup options structure for this keybinding +*/ + +static gpointer remember_setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node) { + xmlNodePtr n; + Options *o = g_new0(Options,1); + + if ((n = parse_find_node("id", node))) { + o->id = parse_string(doc, n); + o->xid = -1; + } else { + g_print("Could not extract id element.\n"); + return NULL; + } + + + return (gpointer)o; +} + +/* +Free the options structure stored with this keybinding +*/ + +static void remember_free_func(gpointer opts) { + + if (remember_popup) { + popup_free(remember_popup); + remember_popup = NULL; + } + Options *o = opts; + g_free(o->id); + g_free(opts); +} + +/* +Function run when keybinding is invoked +*/ + +static gboolean remember_run_func(ObActionsData *data, gpointer opts) { + gchar popuptext[255]; + Options *o = opts; + gboolean found = FALSE; + Rect *a; + + /* callback for list search */ + void activate_list_cb(gpointer data, gpointer user_data) { + Options *o = user_data; + ObClient *client = data; + if (client->window == o->xid) { + /* Switch to client's desktop if needed */ + if (client->desktop != screen_desktop) { + screen_set_desktop(client->desktop, TRUE); + } + /* Activate matching client */ + client_activate(client, FALSE, TRUE, TRUE, TRUE, TRUE); + /* Sets the found flag when a window with the matching ID is found */ + found = TRUE; + } + } + + if (!remember_popup) { + remember_popup = popup_new(); + a = screen_physical_area_primary(FALSE); + popup_position(remember_popup, NorthWestGravity, a->x + 10, a->y + 10); + g_free(a); + } + + /* If this hotkey has no window ID stored */ + if (o->xid == -1) { + /* Remember it in the options structure */ + o->xid = data->client->window; + g_snprintf(popuptext, 254, "Remembered window %s", o->id); + popup_show(remember_popup, popuptext); + ob_main_loop_timeout_remove(ob_main_loop, remember_popup_timeout); + ob_main_loop_timeout_add(ob_main_loop, 2 * G_USEC_PER_SEC, + remember_popup_timeout, NULL, + g_direct_equal, NULL); + } else { + /* Otherwise, search for the window ID in the client list */ + g_list_foreach(client_list, activate_list_cb, o); + + /* If it isn't found, clear the window ID that was stored */ + if (!found) { + o->xid = -1; + return FALSE; + } + } + return TRUE; + +} + +static gboolean remember_popup_timeout(gpointer data) { + popup_hide(remember_popup); + return FALSE; +} Index: openbox/actions/all.c =================================================================== --- openbox/actions/all.c (.../3.4.10) (revision 42) +++ openbox/actions/all.c (.../3.4.10-dr) (revision 42) @@ -38,4 +38,5 @@ action_growtoedge_startup(); action_focustobottom_startup(); action_shadelowerraise_startup(); + action_remember_startup(); } Index: openbox/actions/all.h =================================================================== --- openbox/actions/all.h (.../3.4.10) (revision 42) +++ openbox/actions/all.h (.../3.4.10-dr) (revision 42) @@ -39,5 +39,6 @@ void action_growtoedge_startup(void); void action_focustobottom_startup(void); void action_shadelowerraise_startup(void); +void action_remember_startup(void); #endif Index: Makefile.am =================================================================== --- Makefile.am (.../3.4.10) (revision 42) +++ Makefile.am (.../3.4.10-dr) (revision 42) @@ -160,6 +160,7 @@ openbox/actions/all.c \ openbox/actions/all.h \ openbox/actions/addremovedesktop.c \ + openbox/actions/remember.c \ openbox/actions/breakchroot.c \ openbox/actions/close.c \ openbox/actions/cyclewindows.c \