Plugins can mark edge actions as immediate with the metadata tag <ignore_edge_delay>. --- include/compiz.h | 42 ++++++++++----- metadata/core.xml.in | 7 +++ src/display.c | 5 ++- src/event.c | 142 ++++++++++++++++++++++++++++++++++++++++++++------ src/metadata.c | 12 ++++- 5 files changed, 176 insertions(+), 32 deletions(-) diff --git a/include/compiz.h b/include/compiz.h index cefb7d7..f5d6e95 100644 --- a/include/compiz.h +++ b/include/compiz.h @@ -26,7 +26,7 @@ #ifndef _COMPIZ_H #define _COMPIZ_H -#define ABIVERSION 20070706 +#define ABIVERSION 20070712 #include <stdio.h> #include <sys/time.h> @@ -290,18 +290,19 @@ typedef enum { } CompBindingType; typedef enum { - CompActionStateInitKey = 1 << 0, - CompActionStateTermKey = 1 << 1, - CompActionStateInitButton = 1 << 2, - CompActionStateTermButton = 1 << 3, - CompActionStateInitBell = 1 << 4, - CompActionStateInitEdge = 1 << 5, - CompActionStateTermEdge = 1 << 6, - CompActionStateInitEdgeDnd = 1 << 7, - CompActionStateTermEdgeDnd = 1 << 8, - CompActionStateCommit = 1 << 9, - CompActionStateCancel = 1 << 10, - CompActionStateAutoGrab = 1 << 11 + CompActionStateInitKey = 1 << 0, + CompActionStateTermKey = 1 << 1, + CompActionStateInitButton = 1 << 2, + CompActionStateTermButton = 1 << 3, + CompActionStateInitBell = 1 << 4, + CompActionStateInitEdge = 1 << 5, + CompActionStateTermEdge = 1 << 6, + CompActionStateInitEdgeDnd = 1 << 7, + CompActionStateTermEdgeDnd = 1 << 8, + CompActionStateCommit = 1 << 9, + CompActionStateCancel = 1 << 10, + CompActionStateAutoGrab = 1 << 11, + CompActionStateIgnoreEdgeDelay = 1 << 12 } CompActionState; typedef enum { @@ -587,7 +588,8 @@ typedef int CompFileWatchHandle; #define COMP_DISPLAY_OPTION_TERMINAL 56 #define COMP_DISPLAY_OPTION_RUN_TERMINAL 57 #define COMP_DISPLAY_OPTION_PING_DELAY 58 -#define COMP_DISPLAY_OPTION_NUM 59 +#define COMP_DISPLAY_OPTION_EDGE_DELAY 59 +#define COMP_DISPLAY_OPTION_NUM 60 typedef CompOption *(*GetDisplayOptionsProc) (CompDisplay *display, int *count); @@ -904,6 +906,8 @@ struct _CompDisplay { CompTimeoutHandle autoRaiseHandle; Window autoRaiseWindow; + CompTimeoutHandle edgeDelayHandle; + CompOptionValue plugin; Bool dirtyPluginList; @@ -1107,6 +1111,16 @@ findCursorAtDisplay (CompDisplay *display); /* event.c */ +typedef struct _CompDelayedEdgeSettings +{ + CompDisplay *d; + + unsigned int edge; + unsigned int state; + + CompOption option[7]; +} CompDelayedEdgeSettings; + void handleEvent (CompDisplay *display, XEvent *event); diff --git a/metadata/core.xml.in b/metadata/core.xml.in index 8424ab1..64d418a 100644 --- a/metadata/core.xml.in +++ b/metadata/core.xml.in @@ -44,6 +44,13 @@ <min>0</min> <max>10000</max> </option> + <option name="edge_delay" type="int"> + <_short>Edge Trigger Delay</_short> + <_long>Duration the pointer must reset in a screen edge before an edge action is taken.</_long> + <default>0</default> + <min>0</min> + <max>10000</max> + </option> <option name="close_window" type="action"> <_short>Close Window</_short> <_long>Close active window</_long> diff --git a/src/display.c b/src/display.c index 69e7de3..2c7ed60 100644 --- a/src/display.c +++ b/src/display.c @@ -726,7 +726,8 @@ const CompMetadataOptionInfo coreDisplayOptionInfo[COMP_DISPLAY_OPTION_NUM] = { { "ignore_hints_when_maximized", "bool", 0, 0, 0 }, { "command_terminal", "string", 0, 0, 0 }, { "run_command_terminal", "action", 0, runCommandTerminal, 0 }, - { "ping_delay", "int", "<min>1000</min>", 0, 0 } + { "ping_delay", "int", "<min>1000</min>", 0, 0 }, + { "edge_delay", "int", "<min>0</min>", 0, 0 } }; CompOption * @@ -1981,6 +1982,8 @@ addDisplay (char *name) d->logMessage = logMessage; + d->edgeDelayHandle = 0; + d->display = dpy = XOpenDisplay (name); if (!d->display) { diff --git a/src/event.c b/src/event.c index ab530c2..c12d55d 100644 --- a/src/event.c +++ b/src/event.c @@ -595,6 +595,7 @@ isEdgeAction (CompOption *option, static Bool isEdgeEnterAction (CompOption *option, CompActionState state, + CompActionState ignoreState, unsigned int edge, CompAction **action) { @@ -607,6 +608,15 @@ isEdgeEnterAction (CompOption *option, if (!option->value.action.initiate) return FALSE; + if (ignoreState) + { + if (!((option->value.action.state & CompActionStateIgnoreEdgeDelay) =+ (ignoreState & CompActionStateIgnoreEdgeDelay))) + { + return FALSE; + } + } + *action = &option->value.action; return TRUE; @@ -634,6 +644,7 @@ triggerEdgeEnterBindings (CompDisplay *d, CompOption *option, int nOption, CompActionState state, + CompActionState ignoreState, unsigned int edge, CompOption *argument, int nArgument) @@ -642,7 +653,7 @@ triggerEdgeEnterBindings (CompDisplay *d, while (nOption--) { - if (isEdgeEnterAction (option, state, edge, &action)) + if (isEdgeEnterAction (option, state, ignoreState, edge, &action)) { if ((*action->initiate) (d, action, state, argument, nArgument)) return TRUE; @@ -680,6 +691,62 @@ triggerEdgeLeaveBindings (CompDisplay *d, } static Bool +triggerAllEdgeEnterBindings (CompDisplay *d, + CompActionState state, + CompActionState ignoreState, + unsigned int edge, + CompOption *argument, + int nArgument) +{ + CompOption *option; + int nOption; + CompPlugin *p; + + for (p = getPlugins(); p; p = p->next) + { + if (p->vTable->getDisplayOptions) + { + option = (*p->vTable->getDisplayOptions) (p, d, &nOption); + if (triggerEdgeEnterBindings (d, + option, nOption, + state, ignoreState, edge, + argument, nArgument)) + { + return TRUE; + } + } + } + + option = compGetDisplayOptions (d, &nOption); + if (triggerEdgeEnterBindings(d, + option, nOption, + state, ignoreState, edge, + argument, nArgument)) + { + return TRUE; + } + + return FALSE; +} + +static Bool +delayedEdgeTimeout (void *closure) +{ + CompDelayedEdgeSettings *settings = (CompDelayedEdgeSettings *) closure; + CompDisplay *d = settings->d; + + triggerAllEdgeEnterBindings (d, + settings->state, + ~CompActionStateIgnoreEdgeDelay, + settings->edge, + settings->option, 7); + + free (settings); + + return FALSE; +} + +static Bool handleActionEvent (CompDisplay *d, XEvent *event) { @@ -848,6 +915,16 @@ handleActionEvent (CompDisplay *d, if (edgeWindow && edgeWindow != event->xcrossing.window) { + if (d->edgeDelayHandle) + { + void *closure; + + closure = compRemoveTimeout (d->edgeDelayHandle); + if (closure) + free (closure); + d->edgeDelayHandle = 0; + } + state = CompActionStateTermEdge; edge = 0; @@ -903,10 +980,37 @@ handleActionEvent (CompDisplay *d, if (edge) { + int delay; + CompDelayedEdgeSettings *delayedSettings = NULL; + + delay = d->opt[COMP_DISPLAY_OPTION_EDGE_DELAY].value.i; state = CompActionStateInitEdge; + if (edgeWindow && + edgeWindow != event->xcrossing.window && + d->edgeDelayHandle) + { + void *closure; + + closure = compRemoveTimeout (d->edgeDelayHandle); + if (closure) + free (closure); + d->edgeDelayHandle = 0; + } + edgeWindow = event->xcrossing.window; + if (delay > 0) + { + delayedSettings = malloc (sizeof (CompDelayedEdgeSettings)); + if (delayedSettings) + { + delayedSettings->d = d; + delayedSettings->edge = edge; + delayedSettings->state = state; + } + } + o[0].value.i = event->xcrossing.window; o[1].value.i = d->activeWindow; o[2].value.i = event->xcrossing.state; @@ -918,21 +1022,27 @@ handleActionEvent (CompDisplay *d, o[6].name = "time"; o[6].value.i = event->xcrossing.time; - for (p = getPlugins (); p; p = p->next) + if (delayedSettings) { - if (p->vTable->getDisplayOptions) - { - option = (*p->vTable->getDisplayOptions) (p, d, &nOption); - if (triggerEdgeEnterBindings (d, option, nOption, state, - edge, o, 7)) - return TRUE; - } - } + CompActionState ignoreState; - option = compGetDisplayOptions (d, &nOption); - if (triggerEdgeEnterBindings (d, option, nOption, state, - edge, o, 7)) - return TRUE; + for (i = 0; i < 7; i++) + delayedSettings->option[i] = o[i]; + + d->edgeDelayHandle = compAddTimeout (delay, + delayedEdgeTimeout, + delayedSettings); + + ignoreState = CompActionStateIgnoreEdgeDelay; + if (triggerAllEdgeEnterBindings (d, state, ignoreState, + edge, o, 7)) + return TRUE; + } + else + { + if (triggerAllEdgeEnterBindings (d, state, 0, edge, o, 7)) + return TRUE; + } } } break; case ClientMessage: @@ -1041,14 +1151,14 @@ handleActionEvent (CompDisplay *d, { option = (*p->vTable->getDisplayOptions) (p, d, &nOption); if (triggerEdgeEnterBindings (d, option, nOption, state, - edge, o, 6)) + 0, edge, o, 6)) return TRUE; } } option = compGetDisplayOptions (d, &nOption); if (triggerEdgeEnterBindings (d, option, nOption, state, - edge, o, 6)) + 0, edge, o, 6)) return TRUE; } diff --git a/src/metadata.c b/src/metadata.c index 337c91c..51e7211 100644 --- a/src/metadata.c +++ b/src/metadata.c @@ -851,7 +851,7 @@ initActionState (CompMetadata *metadata, }; int i; CompXPath xPath; - char *grab; + char *grab, *ignoreEdgeDelay; *state = CompActionStateAutoGrab; @@ -864,6 +864,16 @@ initActionState (CompMetadata *metadata, free (grab); } + ignoreEdgeDelay = stringFromMetadataPathElement (metadata, path, + "ignore_edge_delay"); + if (ignoreEdgeDelay) + { + if (strcmp (ignoreEdgeDelay, "true") == 0) + *state |= CompActionStateIgnoreEdgeDelay; + + free (ignoreEdgeDelay); + } + if (!initXPathFromMetadataPathElement (&xPath, metadata, BAD_CAST path, BAD_CAST "allowed")) return; -- 1.5.2.2 --=-x8OTMg0wWYf/MMFSKHv3 Content-Disposition: attachment; filename*0=0003-Also-use-delayed-edge-setting-for-DnD-edge-bindings.patc; filename*1=h Content-Type: application/mbox; name=0003-Also-use-delayed-edge-setting-for-DnD-edge-bindings.patch Content-Transfer-Encoding: 7bit