X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Factions.c;h=bf00c6c83e227fff5599e9e608c902f5026b62a6;hb=HEAD;hp=7854636131d75be20aeb4be85423600015c5fcaf;hpb=1a348576400b26dad3a58a81415c4c833fb4915c;p=chaz%2Fopenbox diff --git a/openbox/actions.c b/openbox/actions.c index 78546361..bf00c6c8 100644 --- a/openbox/actions.c +++ b/openbox/actions.c @@ -1,6 +1,6 @@ /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- - actions.h for the Openbox window manager + actions.c for the Openbox window manager Copyright (c) 2007 Dana Jansens This program is free software; you can redistribute it and/or modify @@ -23,6 +23,7 @@ #include "event.h" #include "config.h" #include "client.h" +#include "focus.h" #include "openbox.h" #include "debug.h" @@ -49,6 +50,9 @@ struct _ObActionsDefinition { } setup; ObActionsDataFreeFunc free; ObActionsRunFunc run; + ObActionsShutdownFunc shutdown; + gboolean modifies_focused_window; + gboolean can_stop; }; struct _ObActionsAct { @@ -79,7 +83,9 @@ void actions_shutdown(gboolean reconfig) /* free all the registered actions */ while (registered) { - actions_definition_unref(registered->data); + ObActionsDefinition *d = registered->data; + if (d->shutdown) d->shutdown(); + actions_definition_unref(d); registered = g_slist_delete_link(registered, registered); } } @@ -99,11 +105,14 @@ ObActionsDefinition* do_register(const gchar *name, return NULL; } - def = g_new(ObActionsDefinition, 1); + def = g_slice_new0(ObActionsDefinition); def->ref = 1; def->name = g_strdup(name); def->free = free; def->run = run; + def->shutdown = NULL; + def->modifies_focused_window = TRUE; + def->can_stop = FALSE; registered = g_slist_prepend(registered, def); return def; @@ -135,6 +144,54 @@ gboolean actions_register(const gchar *name, return def != NULL; } +gboolean actions_set_shutdown(const gchar *name, + ObActionsShutdownFunc shutdown) +{ + GSList *it; + ObActionsDefinition *def; + + for (it = registered; it; it = g_slist_next(it)) { + def = it->data; + if (!g_ascii_strcasecmp(name, def->name)) { + def->shutdown = shutdown; + return TRUE; + } + } + return FALSE; +} + +gboolean actions_set_modifies_focused_window(const gchar *name, + gboolean modifies) +{ + GSList *it; + ObActionsDefinition *def; + + for (it = registered; it; it = g_slist_next(it)) { + def = it->data; + if (!g_ascii_strcasecmp(name, def->name)) { + def->modifies_focused_window = modifies; + return TRUE; + } + } + return FALSE; +} + +gboolean actions_set_can_stop(const gchar *name, + gboolean can_stop) +{ + GSList *it; + ObActionsDefinition *def; + + for (it = registered; it; it = g_slist_next(it)) { + def = it->data; + if (!g_ascii_strcasecmp(name, def->name)) { + def->can_stop = can_stop; + return TRUE; + } + } + return FALSE; +} + static void actions_definition_ref(ObActionsDefinition *def) { ++def->ref; @@ -144,7 +201,7 @@ static void actions_definition_unref(ObActionsDefinition *def) { if (def && --def->ref == 0) { g_free(def->name); - g_free(def); + g_slice_free(ObActionsDefinition, def); } } @@ -164,7 +221,7 @@ static ObActionsAct* actions_build_act_from_string(const gchar *name) /* if we found the action */ if (def) { - act = g_new(ObActionsAct, 1); + act = g_slice_new(ObActionsAct); act->ref = 1; act->def = def; actions_definition_ref(act->def); @@ -208,7 +265,7 @@ ObActionsAct* actions_parse(xmlNodePtr node) gchar *name; ObActionsAct *act = NULL; - if (obt_parse_attr_string(node, "name", &name)) { + if (obt_xml_attr_string(node, "name", &name)) { if ((act = actions_build_act_from_string(name))) { /* there is more stuff to parse here */ if (act->def->canbeinteractive) { @@ -248,7 +305,7 @@ void actions_act_unref(ObActionsAct *act) act->def->free(act->options); /* unref the definition */ actions_definition_unref(act->def); - g_free(act); + g_slice_free(ObActionsAct, act); } } @@ -280,6 +337,7 @@ void actions_run_acts(GSList *acts, struct _ObClient *client) { GSList *it; + gboolean update_user_time; /* Don't allow saving the initial state when running things from the menu */ @@ -289,6 +347,7 @@ void actions_run_acts(GSList *acts, if (x < 0 && y < 0) screen_pointer_pos(&x, &y); + update_user_time = FALSE; for (it = acts; it; it = g_slist_next(it)) { ObActionsData data; ObActionsAct *act = it->data; @@ -315,17 +374,26 @@ void actions_run_acts(GSList *acts, /* fire the action's run function with this data */ if (ok) { if (!act->def->run(&data, act->options)) { - if (actions_act_is_interactive(act)) + if (actions_act_is_interactive(act)) { actions_interactive_end_act(); + } + if (client && client == focus_client && + act->def->modifies_focused_window) + { + update_user_time = TRUE; + } } else { - /* make sure its interactive if it returned TRUE */ - g_assert(act->i_input); + /* make sure its interactive or allowed to stop + if it returned TRUE */ + g_assert(act->i_input || act->def->can_stop); /* no actions are run after the interactive one */ break; } } } + if (update_user_time) + event_update_user_time(); } gboolean actions_interactive_act_running(void) @@ -363,13 +431,19 @@ static gboolean actions_interactive_begin_act(ObActionsAct *act, guint state) static void actions_interactive_end_act(void) { if (interactive_act) { + ObActionsAct *ia = interactive_act; + + /* set this to NULL first so the i_post() function can't cause this to + get called again (if it decides it wants to cancel any ongoing + interactive action). */ + interactive_act = NULL; + ungrab_keyboard(); - if (interactive_act->i_post) - interactive_act->i_post(interactive_act->options); + if (ia->i_post) + ia->i_post(ia->options); - actions_act_unref(interactive_act); - interactive_act = NULL; + actions_act_unref(ia); } } @@ -378,6 +452,7 @@ gboolean actions_interactive_input_event(XEvent *e) gboolean used = FALSE; if (interactive_act) { if (!interactive_act->i_input(interactive_initial_state, e, + grab_input_context(), interactive_act->options, &used)) { used = TRUE; /* if it cancelled the action then it has to of @@ -408,13 +483,19 @@ void actions_client_move(ObActionsData *data, gboolean start) are ignored during a grab, so don't force fake ones when they should be ignored */ - if ((c = client_under_pointer()) && c != data->client && - !grab_on_pointer()) - { - ob_debug_type(OB_DEBUG_FOCUS, - "Generating fake enter because we did a " - "mouse-event action"); - event_enter_client(c); + if (!grab_on_pointer()) { + if ((c = client_under_pointer()) && c != data->client) { + ob_debug_type(OB_DEBUG_FOCUS, + "Generating fake enter because we did a " + "mouse-event action"); + event_enter_client(c); + } + else if (!c && c != data->client) { + ob_debug_type(OB_DEBUG_FOCUS, + "Generating fake leave because we did a " + "mouse-event action"); + event_leave_client(data->client); + } } } else if (!data->button && !config_focus_under_mouse)