mouse and key bindings plugins work. segfault somewhere still on shutdown
This commit is contained in:
parent
51b93d9c4c
commit
4bcd03b2d0
15 changed files with 782 additions and 208 deletions
190
openbox/action.c
190
openbox/action.c
|
@ -1,172 +1,205 @@
|
|||
#include "client.h"
|
||||
#include "stacking.h"
|
||||
#include "frame.h"
|
||||
#include "screen.h"
|
||||
#include "action.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
void action_execute(char *path)
|
||||
Action *action_new(void (*func)(union ActionData *data))
|
||||
{
|
||||
Action *a = g_new(Action, 1);
|
||||
a->func = func;
|
||||
|
||||
/* deal with pointers */
|
||||
if (func == action_execute)
|
||||
a->data.execute.path = NULL;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
void action_free(Action *a)
|
||||
{
|
||||
/* deal with pointers */
|
||||
if (a->func == action_execute)
|
||||
g_free(a->data.execute.path);
|
||||
|
||||
g_free(a);
|
||||
}
|
||||
|
||||
void action_execute(union ActionData *data)
|
||||
{
|
||||
GError *e;
|
||||
if (!g_spawn_command_line_async(path, &e)) {
|
||||
g_warning("failed to execute '%s': %s", path, e->message);
|
||||
if (!g_spawn_command_line_async(data->execute.path, &e)) {
|
||||
g_warning("failed to execute '%s': %s",
|
||||
data->execute.path, e->message);
|
||||
}
|
||||
}
|
||||
|
||||
void action_iconify(Client *c)
|
||||
void action_iconify(union ActionData *data)
|
||||
{
|
||||
client_iconify(c, TRUE, TRUE);
|
||||
client_iconify(data->client.c, TRUE, TRUE);
|
||||
}
|
||||
|
||||
void action_raise(Client *c)
|
||||
void action_raise(union ActionData *data)
|
||||
{
|
||||
stacking_raise(c);
|
||||
stacking_raise(data->client.c);
|
||||
}
|
||||
|
||||
void action_lower(Client *c)
|
||||
void action_lower(union ActionData *data)
|
||||
{
|
||||
stacking_lower(c);
|
||||
stacking_lower(data->client.c);
|
||||
}
|
||||
|
||||
void action_close(Client *c)
|
||||
void action_close(union ActionData *data)
|
||||
{
|
||||
client_close(c);
|
||||
client_close(data->client.c);
|
||||
}
|
||||
|
||||
void action_shade(Client *c)
|
||||
void action_shade(union ActionData *data)
|
||||
{
|
||||
client_shade(c, TRUE);
|
||||
client_shade(data->client.c, TRUE);
|
||||
}
|
||||
|
||||
void action_unshade(Client *c)
|
||||
void action_unshade(union ActionData *data)
|
||||
{
|
||||
client_shade(c, FALSE);
|
||||
client_shade(data->client.c, FALSE);
|
||||
}
|
||||
|
||||
void action_toggle_shade(Client *c)
|
||||
void action_toggle_shade(union ActionData *data)
|
||||
{
|
||||
client_shade(c, !c->shaded);
|
||||
client_shade(data->client.c, !data->client.c->shaded);
|
||||
}
|
||||
|
||||
void action_toggle_omnipresent(Client *c)
|
||||
void action_toggle_omnipresent(union ActionData *data)
|
||||
{
|
||||
client_set_desktop(c, c->desktop == DESKTOP_ALL ?
|
||||
client_set_desktop(data->client.c, data->client.c->desktop == DESKTOP_ALL ?
|
||||
screen_desktop : DESKTOP_ALL);
|
||||
}
|
||||
|
||||
void action_move_relative(Client *c, int dx, int dy)
|
||||
void action_move_relative(union ActionData *data)
|
||||
{
|
||||
client_configure(c, Corner_TopLeft, c->area.x + dx, c->area.y + dy,
|
||||
Client *c = data->relative.c;
|
||||
client_configure(c, Corner_TopLeft,
|
||||
c->area.x + data->relative.dx,
|
||||
c->area.y + data->relative.dy,
|
||||
c->area.width, c->area.height, TRUE, TRUE);
|
||||
}
|
||||
|
||||
void action_resize_relative(Client *c, int dx, int dy)
|
||||
void action_resize_relative(union ActionData *data)
|
||||
{
|
||||
Client *c = data->relative.c;
|
||||
client_configure(c, Corner_TopLeft, c->area.x, c->area.y,
|
||||
c->area.width + dx, c->area.height + dy, TRUE, TRUE);
|
||||
c->area.width + data->relative.dx,
|
||||
c->area.height + data->relative.dy, TRUE, TRUE);
|
||||
}
|
||||
|
||||
void action_maximize_full(Client *c)
|
||||
void action_maximize_full(union ActionData *data)
|
||||
{
|
||||
client_maximize(c, TRUE, 0, TRUE);
|
||||
client_maximize(data->client.c, TRUE, 0, TRUE);
|
||||
}
|
||||
|
||||
void action_unmaximize_full(Client *c)
|
||||
void action_unmaximize_full(union ActionData *data)
|
||||
{
|
||||
client_maximize(c, FALSE, 0, TRUE);
|
||||
client_maximize(data->client.c, FALSE, 0, TRUE);
|
||||
}
|
||||
|
||||
void action_toggle_maximize_full(Client *c)
|
||||
void action_toggle_maximize_full(union ActionData *data)
|
||||
{
|
||||
client_maximize(c, !(c->max_horz || c->max_vert), 0, TRUE);
|
||||
client_maximize(data->client.c,
|
||||
!(data->client.c->max_horz || data->client.c->max_vert),
|
||||
0, TRUE);
|
||||
}
|
||||
|
||||
void action_maximize_horz(Client *c)
|
||||
void action_maximize_horz(union ActionData *data)
|
||||
{
|
||||
client_maximize(c, TRUE, 1, TRUE);
|
||||
client_maximize(data->client.c, TRUE, 1, TRUE);
|
||||
}
|
||||
|
||||
void action_unmaximize_horz(Client *c)
|
||||
void action_unmaximize_horz(union ActionData *data)
|
||||
{
|
||||
client_maximize(c, FALSE, 1, TRUE);
|
||||
client_maximize(data->client.c, FALSE, 1, TRUE);
|
||||
}
|
||||
|
||||
void action_toggle_maximize_horz(Client *c)
|
||||
void action_toggle_maximize_horz(union ActionData *data)
|
||||
{
|
||||
client_maximize(c, !c->max_horz, 1, TRUE);
|
||||
client_maximize(data->client.c, !data->client.c->max_horz, 1, TRUE);
|
||||
}
|
||||
|
||||
void action_maximize_vert(Client *c)
|
||||
void action_maximize_vert(union ActionData *data)
|
||||
{
|
||||
client_maximize(c, TRUE, 2, TRUE);
|
||||
client_maximize(data->client.c, TRUE, 2, TRUE);
|
||||
}
|
||||
|
||||
void action_unmaximize_vert(Client *c)
|
||||
void action_unmaximize_vert(union ActionData *data)
|
||||
{
|
||||
client_maximize(c, FALSE, 2, TRUE);
|
||||
client_maximize(data->client.c, FALSE, 2, TRUE);
|
||||
}
|
||||
|
||||
void action_toggle_maximize_vert(Client *c)
|
||||
void action_toggle_maximize_vert(union ActionData *data)
|
||||
{
|
||||
client_maximize(c, !c->max_vert, 2, TRUE);
|
||||
client_maximize(data->client.c, !data->client.c->max_vert, 2, TRUE);
|
||||
}
|
||||
|
||||
void action_send_to_desktop(Client *c, guint desktop)
|
||||
void action_send_to_desktop(union ActionData *data)
|
||||
{
|
||||
if (desktop < screen_num_desktops || desktop == DESKTOP_ALL)
|
||||
client_set_desktop(c, desktop);
|
||||
if (data->sendto.desktop < screen_num_desktops ||
|
||||
data->sendto.desktop == DESKTOP_ALL)
|
||||
client_set_desktop(data->sendto.c, data->sendto.desktop);
|
||||
}
|
||||
|
||||
void action_send_to_next_desktop(Client *c, gboolean wrap, gboolean follow)
|
||||
void action_send_to_next_desktop(union ActionData *data)
|
||||
{
|
||||
guint d;
|
||||
|
||||
d = screen_desktop + 1;
|
||||
if (d >= screen_num_desktops) {
|
||||
if (!wrap) return;
|
||||
if (!data->sendtonextprev.wrap) return;
|
||||
d = 0;
|
||||
}
|
||||
client_set_desktop(c, d);
|
||||
if (follow) screen_set_desktop(d);
|
||||
client_set_desktop(data->sendtonextprev.c, d);
|
||||
if (data->sendtonextprev.follow) screen_set_desktop(d);
|
||||
}
|
||||
|
||||
void action_send_to_previous_desktop(Client *c, gboolean wrap, gboolean follow)
|
||||
void action_send_to_previous_desktop(union ActionData *data)
|
||||
{
|
||||
guint d;
|
||||
|
||||
d = screen_desktop - 1;
|
||||
if (d >= screen_num_desktops) {
|
||||
if (!wrap) return;
|
||||
if (!data->sendtonextprev.wrap) return;
|
||||
d = screen_num_desktops - 1;
|
||||
}
|
||||
client_set_desktop(c, d);
|
||||
if (follow) screen_set_desktop(d);
|
||||
client_set_desktop(data->sendtonextprev.c, d);
|
||||
if (data->sendtonextprev.follow) screen_set_desktop(d);
|
||||
}
|
||||
|
||||
void action_desktop(guint desktop)
|
||||
void action_desktop(union ActionData *data)
|
||||
{
|
||||
if (desktop < screen_num_desktops || desktop == DESKTOP_ALL)
|
||||
screen_set_desktop(desktop);
|
||||
if (data->desktop.desk < screen_num_desktops ||
|
||||
data->desktop.desk == DESKTOP_ALL)
|
||||
screen_set_desktop(data->desktop.desk);
|
||||
}
|
||||
|
||||
void action_next_desktop(gboolean wrap)
|
||||
void action_next_desktop(union ActionData *data)
|
||||
{
|
||||
guint d;
|
||||
|
||||
d = screen_desktop + 1;
|
||||
if (d >= screen_num_desktops) {
|
||||
if (!wrap) return;
|
||||
if (!data->nextprevdesktop.wrap) return;
|
||||
d = 0;
|
||||
}
|
||||
screen_set_desktop(d);
|
||||
}
|
||||
|
||||
void action_previous_desktop(gboolean wrap)
|
||||
void action_previous_desktop(union ActionData *data)
|
||||
{
|
||||
guint d;
|
||||
|
||||
d = screen_desktop - 1;
|
||||
if (d >= screen_num_desktops) {
|
||||
if (!wrap) return;
|
||||
if (!data->nextprevdesktop.wrap) return;
|
||||
d = screen_num_desktops - 1;
|
||||
}
|
||||
screen_set_desktop(d);
|
||||
|
@ -267,7 +300,7 @@ static guint translate_row_col(guint r, guint c)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void action_next_desktop_column(gboolean wrap)
|
||||
void action_next_desktop_column(union ActionData *data)
|
||||
{
|
||||
guint r, c, d;
|
||||
|
||||
|
@ -275,7 +308,7 @@ void action_next_desktop_column(gboolean wrap)
|
|||
++c;
|
||||
d = translate_row_col(r, c);
|
||||
if (d >= screen_num_desktops) {
|
||||
if (!wrap) return;
|
||||
if (!data->nextprevdesktop.wrap) return;
|
||||
c = 0;
|
||||
}
|
||||
if (d >= screen_num_desktops)
|
||||
|
@ -285,7 +318,7 @@ void action_next_desktop_column(gboolean wrap)
|
|||
screen_set_desktop(d);
|
||||
}
|
||||
|
||||
void action_previous_desktop_column(gboolean wrap)
|
||||
void action_previous_desktop_column(union ActionData *data)
|
||||
{
|
||||
guint r, c, d;
|
||||
|
||||
|
@ -293,7 +326,7 @@ void action_previous_desktop_column(gboolean wrap)
|
|||
--c;
|
||||
d = translate_row_col(r, c);
|
||||
if (d >= screen_num_desktops) {
|
||||
if (!wrap) return;
|
||||
if (!data->nextprevdesktop.wrap) return;
|
||||
c = screen_desktop_layout.columns - 1;
|
||||
}
|
||||
if (d >= screen_num_desktops)
|
||||
|
@ -303,7 +336,7 @@ void action_previous_desktop_column(gboolean wrap)
|
|||
screen_set_desktop(d);
|
||||
}
|
||||
|
||||
void action_next_desktop_row(gboolean wrap)
|
||||
void action_next_desktop_row(union ActionData *data)
|
||||
{
|
||||
guint r, c, d;
|
||||
|
||||
|
@ -311,7 +344,7 @@ void action_next_desktop_row(gboolean wrap)
|
|||
++r;
|
||||
d = translate_row_col(r, c);
|
||||
if (d >= screen_num_desktops) {
|
||||
if (!wrap) return;
|
||||
if (!data->nextprevdesktop.wrap) return;
|
||||
r = 0;
|
||||
}
|
||||
if (d >= screen_num_desktops)
|
||||
|
@ -321,7 +354,7 @@ void action_next_desktop_row(gboolean wrap)
|
|||
screen_set_desktop(d);
|
||||
}
|
||||
|
||||
void action_previous_desktop_row(gboolean wrap)
|
||||
void action_previous_desktop_row(union ActionData *data)
|
||||
{
|
||||
guint r, c, d;
|
||||
|
||||
|
@ -329,7 +362,7 @@ void action_previous_desktop_row(gboolean wrap)
|
|||
--r;
|
||||
d = translate_row_col(r, c);
|
||||
if (d >= screen_num_desktops) {
|
||||
if (!wrap) return;
|
||||
if (!data->nextprevdesktop.wrap) return;
|
||||
c = screen_desktop_layout.rows - 1;
|
||||
}
|
||||
if (d >= screen_num_desktops)
|
||||
|
@ -339,8 +372,29 @@ void action_previous_desktop_row(gboolean wrap)
|
|||
screen_set_desktop(d);
|
||||
}
|
||||
|
||||
void action_toggle_decorations(Client *c)
|
||||
void action_toggle_decorations(union ActionData *data)
|
||||
{
|
||||
Client *c = data->client.c;
|
||||
c->disabled_decorations = c->disabled_decorations ? 0 : ~0;
|
||||
client_setup_decor_and_functions(c);
|
||||
}
|
||||
|
||||
void action_move(union ActionData *data)
|
||||
{
|
||||
Client *c = data->move.c;
|
||||
int x = data->move.x;
|
||||
int y = data->move.y;
|
||||
|
||||
client_configure(c, Corner_TopLeft, x, y, c->area.width, c->area.height,
|
||||
TRUE, data->move.final);
|
||||
}
|
||||
|
||||
void action_resize(union ActionData *data)
|
||||
{
|
||||
Client *c = data->resize.c;
|
||||
int w = data->resize.x - c->frame->size.left - c->frame->size.right;
|
||||
int h = data->resize.y - c->frame->size.top - c->frame->size.bottom;
|
||||
|
||||
client_configure(c, data->resize.corner, c->area.x, c->area.y, w, h,
|
||||
TRUE, data->resize.final);
|
||||
}
|
||||
|
|
211
openbox/action.h
211
openbox/action.h
|
@ -3,70 +3,155 @@
|
|||
|
||||
#include "client.h"
|
||||
|
||||
typedef enum {
|
||||
Action_Execute,
|
||||
Action_Iconify,
|
||||
Action_Raise,
|
||||
Action_Lower,
|
||||
Action_Close,
|
||||
Action_Shade,
|
||||
Action_Unshade,
|
||||
Action_ToggleShade,
|
||||
Action_ToggleOmnipresent,
|
||||
Action_MoveRelative,
|
||||
Action_ResizeRelative,
|
||||
Action_MaximizeFull,
|
||||
Action_UnmaximizeFull,
|
||||
Action_ToggleMaximizeFull,
|
||||
Action_MaximizeHorz,
|
||||
Action_UnmaximizeHorz,
|
||||
Action_ToggleMaximizeHorz,
|
||||
Action_MaximizeVert,
|
||||
Action_UnmaximizeVert,
|
||||
Action_ToggleMaximizeVert,
|
||||
Action_SendToDesktop,
|
||||
Action_SendToNextDesktop,
|
||||
Action_SendToPreviousDesktop,
|
||||
Action_Desktop,
|
||||
Action_NextDesktop,
|
||||
Action_PreviousDesktop,
|
||||
Action_NextDesktopColumn,
|
||||
Action_PreviousDesktopColumn,
|
||||
Action_NextDesktopRow,
|
||||
Action_PreviousDesktopRow,
|
||||
Action_ToggleDecorations
|
||||
/* These have to all have a Client* at the top even if they don't use it, so
|
||||
that I can set it blindly later on. So every function will have a Client*
|
||||
available (possibly NULL though) if it wants it.
|
||||
*/
|
||||
|
||||
struct AnyAction {
|
||||
Client *c;
|
||||
};
|
||||
|
||||
struct Execute {
|
||||
Client *c;
|
||||
char *path;
|
||||
};
|
||||
|
||||
struct ClientAction {
|
||||
Client *c;
|
||||
};
|
||||
|
||||
struct MoveResizeRelative {
|
||||
Client *c;
|
||||
int dx;
|
||||
int dy;
|
||||
};
|
||||
|
||||
struct SendToDesktop {
|
||||
Client *c;
|
||||
guint desktop;
|
||||
};
|
||||
|
||||
struct SendToNextPreviousDesktop {
|
||||
Client *c;
|
||||
gboolean wrap;
|
||||
gboolean follow;
|
||||
};
|
||||
|
||||
struct Desktop {
|
||||
Client *c;
|
||||
guint desk;
|
||||
};
|
||||
|
||||
struct NextPreviousDesktop {
|
||||
Client *c;
|
||||
gboolean wrap;
|
||||
};
|
||||
|
||||
struct Move {
|
||||
Client *c;
|
||||
int x;
|
||||
int y;
|
||||
gboolean final;
|
||||
};
|
||||
|
||||
struct Resize {
|
||||
Client *c;
|
||||
int x;
|
||||
int y;
|
||||
gboolean final;
|
||||
Corner corner;
|
||||
};
|
||||
|
||||
union ActionData {
|
||||
struct AnyAction any;
|
||||
struct Execute execute;
|
||||
struct ClientAction client;
|
||||
struct MoveResizeRelative relative;
|
||||
struct SendToDesktop sendto;
|
||||
struct SendToNextPreviousDesktop sendtonextprev;
|
||||
struct Desktop desktop;
|
||||
struct NextPreviousDesktop nextprevdesktop;
|
||||
struct Move move;
|
||||
struct Resize resize;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
/* The func member acts like an enum to tell which one of the structs in
|
||||
the data union are valid.
|
||||
*/
|
||||
void (*func)(union ActionData *data);
|
||||
union ActionData data;
|
||||
} Action;
|
||||
|
||||
void action_execute(char *path);
|
||||
void action_iconify(Client *c);
|
||||
void action_raise(Client *c);
|
||||
void action_lower(Client *c);
|
||||
void action_close(Client *c);
|
||||
void action_shade(Client *c);
|
||||
void action_unshade(Client *c);
|
||||
void action_toggle_shade(Client *c);
|
||||
void action_toggle_omnipresent(Client *c);
|
||||
void action_move_relative(Client *c, int dx, int dy);
|
||||
void action_resize_relative(Client *c, int dx, int dy);
|
||||
void action_maximize_full(Client *c);
|
||||
void action_unmaximize_full(Client *c);
|
||||
void action_toggle_maximize_full(Client *c);
|
||||
void action_maximize_horz(Client *c);
|
||||
void action_unmaximize_horz(Client *c);
|
||||
void action_toggle_maximize_horz(Client *c);
|
||||
void action_maximize_vert(Client *c);
|
||||
void action_unmaximize_vert(Client *c);
|
||||
void action_toggle_maximize_vert(Client *c);
|
||||
void action_send_to_desktop(Client *c, guint desktop);
|
||||
void action_send_to_next_desktop(Client *c, gboolean wrap, gboolean follow);
|
||||
void action_send_to_previous_desktop(Client *c, gboolean wrap,gboolean follow);
|
||||
void action_desktop(guint desktop);
|
||||
void action_next_desktop(gboolean wrap);
|
||||
void action_previous_desktop(gboolean wrap);
|
||||
void action_next_desktop_column(gboolean wrap);
|
||||
void action_previous_desktop_column(gboolean wrap);
|
||||
void action_next_desktop_row(gboolean wrap);
|
||||
void action_previous_desktop_row(gboolean wrap);
|
||||
void action_toggle_decorations(Client *c);
|
||||
Action *action_new(void (*func)(union ActionData *data));
|
||||
void action_free(Action *a);
|
||||
|
||||
/* Execute */
|
||||
void action_execute(union ActionData *data);
|
||||
/* ClientAction */
|
||||
void action_iconify(union ActionData *data);
|
||||
/* ClientAction */
|
||||
void action_raise(union ActionData *data);
|
||||
/* ClientAction */
|
||||
void action_lower(union ActionData *data);
|
||||
/* ClientAction */
|
||||
void action_close(union ActionData *data);
|
||||
/* ClientAction */
|
||||
void action_shade(union ActionData *data);
|
||||
/* ClientAction */
|
||||
void action_unshade(union ActionData *data);
|
||||
/* ClientAction */
|
||||
void action_toggle_shade(union ActionData *data);
|
||||
/* ClientAction */
|
||||
void action_toggle_omnipresent(union ActionData *data);
|
||||
/* MoveResizeRelative */
|
||||
void action_move_relative(union ActionData *data);
|
||||
/* MoveResizeRelative */
|
||||
void action_resize_relative(union ActionData *data);
|
||||
/* ClientAction */
|
||||
void action_maximize_full(union ActionData *data);
|
||||
/* ClientAction */
|
||||
void action_unmaximize_full(union ActionData *data);
|
||||
/* ClientAction */
|
||||
void action_toggle_maximize_full(union ActionData *data);
|
||||
/* ClientAction */
|
||||
void action_maximize_horz(union ActionData *data);
|
||||
/* ClientAction */
|
||||
void action_unmaximize_horz(union ActionData *data);
|
||||
/* ClientAction */
|
||||
void action_toggle_maximize_horz(union ActionData *data);
|
||||
/* ClientAction */
|
||||
void action_maximize_vert(union ActionData *data);
|
||||
/* ClientAction */
|
||||
void action_unmaximize_vert(union ActionData *data);
|
||||
/* ClientAction */
|
||||
void action_toggle_maximize_vert(union ActionData *data);
|
||||
/* SendToDesktop */
|
||||
void action_send_to_desktop(union ActionData *data);
|
||||
/* SendToNextPreviousDesktop */
|
||||
void action_send_to_next_desktop(union ActionData *data);
|
||||
/* SendToNextPreviousDesktop */
|
||||
void action_send_to_previous_desktop(union ActionData *data);
|
||||
/* Desktop */
|
||||
void action_desktop(union ActionData *data);
|
||||
/* NextPreviousDesktop */
|
||||
void action_next_desktop(union ActionData *data);
|
||||
/* NextPreviousDesktop */
|
||||
void action_previous_desktop(union ActionData *data);
|
||||
/* NextPreviousDesktop */
|
||||
void action_next_desktop_column(union ActionData *data);
|
||||
/* NextPreviousDesktop */
|
||||
void action_previous_desktop_column(union ActionData *data);
|
||||
/* NextPreviousDesktop */
|
||||
void action_next_desktop_row(union ActionData *data);
|
||||
/* NextPreviousDesktop */
|
||||
void action_previous_desktop_row(union ActionData *data);
|
||||
/* ClientAction */
|
||||
void action_toggle_decorations(union ActionData *data);
|
||||
/* Move */
|
||||
void action_move(union ActionData *data);
|
||||
/* Resize */
|
||||
void action_resize(union ActionData *data);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -21,7 +21,7 @@ void grab_pointer(gboolean grab, Cursor cur)
|
|||
if (grab) {
|
||||
if (pgrabs++ == 0)
|
||||
XGrabPointer(ob_display, ob_root, False, 0, GrabModeAsync,
|
||||
GrabModeSync, FALSE, cur, CurrentTime);
|
||||
GrabModeAsync, FALSE, cur, CurrentTime);
|
||||
} else if (pgrabs > 0) {
|
||||
if (--pgrabs == 0)
|
||||
XUngrabPointer(ob_display, CurrentTime);
|
||||
|
|
|
@ -7,9 +7,9 @@ CPPFLAGS=$(XFT_CFLAGS) $(GLIB_CFLAGS) @CPPFLAGS@ \
|
|||
plugin_LTLIBRARIES=keyboard.la
|
||||
|
||||
keyboard_la_LDFLAGS=-module -avoid-version
|
||||
keyboard_la_SOURCES=keyboard.c tree.c translate.c keyaction.c
|
||||
keyboard_la_SOURCES=keyboard.c tree.c translate.c
|
||||
|
||||
noinst_HEADERS=keyboard.h tree.h translate.h keyaction.h
|
||||
noinst_HEADERS=keyboard.h tree.h translate.h
|
||||
|
||||
MAINTAINERCLEANFILES= Makefile.in
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include "../../kernel/action.h"
|
||||
#include "tree.h"
|
||||
#include "keyboard.h"
|
||||
#include "keyaction.h"
|
||||
#include <glib.h>
|
||||
|
||||
KeyBindingTree *firstnode;
|
||||
|
@ -21,6 +20,7 @@ static void grab_keys(gboolean grab)
|
|||
} else {
|
||||
KeyBindingTree *p = firstnode;
|
||||
while (p) {
|
||||
/* XXX grab all lock keys too */
|
||||
XGrabKey(ob_display, p->key, p->state, ob_root, FALSE,
|
||||
GrabModeAsync, GrabModeSync);
|
||||
p = p->next_sibling;
|
||||
|
@ -38,56 +38,43 @@ static void reset_chains()
|
|||
}
|
||||
}
|
||||
|
||||
static void clearall()
|
||||
{
|
||||
grab_keys(FALSE);
|
||||
tree_destroy(firstnode);
|
||||
firstnode = NULL;
|
||||
grab_keys(TRUE);
|
||||
}
|
||||
|
||||
static gboolean bind(GList *keylist, KeyAction *action)
|
||||
static gboolean kbind(GList *keylist, Action *action)
|
||||
{
|
||||
KeyBindingTree *tree, *t;
|
||||
gboolean conflict;
|
||||
|
||||
g_assert(keylist != NULL);
|
||||
g_assert(action != NULL);
|
||||
|
||||
if (!(tree = tree_build(keylist))) {
|
||||
g_warning("invalid binding");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
t = tree_find(tree, &conflict);
|
||||
if (conflict) {
|
||||
g_warning("conflict with binding");
|
||||
tree_destroy(tree);
|
||||
return FALSE;
|
||||
}
|
||||
if (t != NULL) {
|
||||
if ((t = tree_find(tree, &conflict)) != NULL) {
|
||||
/* already bound to something */
|
||||
g_warning("keychain is already bound");
|
||||
tree_destroy(tree);
|
||||
return FALSE;
|
||||
}
|
||||
if (conflict) {
|
||||
g_warning("conflict with binding");
|
||||
tree_destroy(tree);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* grab the server here to make sure no key pressed go missed */
|
||||
/* grab the server here to make sure no key presses go missed */
|
||||
grab_server(TRUE);
|
||||
|
||||
grab_keys(FALSE);
|
||||
|
||||
/* set the function */
|
||||
/* set the action */
|
||||
t = tree;
|
||||
while (t->first_child) t = t->first_child;
|
||||
t->action.action = action->action;
|
||||
t->action.type[0] = action->type[0];
|
||||
t->action.type[1] = action->type[1];
|
||||
t->action.data[0] = action->data[0];
|
||||
t->action.data[1] = action->data[1];
|
||||
|
||||
/* assimilate this built tree into the main tree */
|
||||
tree_assimilate(tree); /* assimilation destroys/uses the tree */
|
||||
t->action = action;
|
||||
/* assimilate this built tree into the main tree. assimilation
|
||||
destroys/uses the tree */
|
||||
tree_assimilate(tree);
|
||||
|
||||
grab_keys(TRUE);
|
||||
|
||||
grab_server(FALSE);
|
||||
|
||||
return TRUE;
|
||||
|
@ -117,7 +104,14 @@ static void press(ObEvent *e, void *foo)
|
|||
}
|
||||
curpos = p;
|
||||
} else {
|
||||
keyaction_do(&p->action, focus_client);
|
||||
if (p->action->func != NULL) {
|
||||
p->action->data.any.c = focus_client;
|
||||
|
||||
g_assert(!(p->action->func == action_move ||
|
||||
p->action->func == action_resize));
|
||||
|
||||
p->action->func(&p->action->data);
|
||||
}
|
||||
|
||||
XAllowEvents(ob_display, AsyncKeyboard, CurrentTime);
|
||||
reset_chains();
|
||||
|
@ -132,49 +126,47 @@ static void press(ObEvent *e, void *foo)
|
|||
static void binddef()
|
||||
{
|
||||
GList *list = g_list_append(NULL, NULL);
|
||||
KeyAction a;
|
||||
Action *a;
|
||||
|
||||
/* When creating an Action struct, all of the data elements in the
|
||||
appropriate struct need to be set, except the Client*, which will be set
|
||||
at call-time when then action function is used.
|
||||
*/
|
||||
|
||||
list->data = "C-Right";
|
||||
a.action = Action_NextDesktop;
|
||||
keyaction_set_bool(&a, 0, TRUE);
|
||||
keyaction_set_none(&a, 1);
|
||||
bind(list, &a);
|
||||
a = action_new(action_next_desktop);
|
||||
a->data.nextprevdesktop.wrap = TRUE;
|
||||
kbind(list, a);
|
||||
|
||||
list->data = "C-Left";
|
||||
a.action = Action_PreviousDesktop;
|
||||
keyaction_set_bool(&a, 0, TRUE);
|
||||
keyaction_set_none(&a, 1);
|
||||
bind(list, &a);
|
||||
a = action_new(action_previous_desktop);
|
||||
a->data.nextprevdesktop.wrap = TRUE;
|
||||
kbind(list, a);
|
||||
|
||||
list->data = "C-1";
|
||||
a.action = Action_Desktop;
|
||||
keyaction_set_uint(&a, 0, 0);
|
||||
keyaction_set_none(&a, 1);
|
||||
bind(list, &a);
|
||||
a = action_new(action_desktop);
|
||||
a->data.desktop.desk = 0;
|
||||
kbind(list, a);
|
||||
|
||||
list->data = "C-2";
|
||||
a.action = Action_Desktop;
|
||||
keyaction_set_uint(&a, 0, 1);
|
||||
keyaction_set_none(&a, 1);
|
||||
bind(list, &a);
|
||||
list->data = "C-2";
|
||||
a = action_new(action_desktop);
|
||||
a->data.desktop.desk = 1;
|
||||
kbind(list, a);
|
||||
|
||||
list->data = "C-3";
|
||||
a.action = Action_Desktop;
|
||||
keyaction_set_uint(&a, 0, 2);
|
||||
keyaction_set_none(&a, 1);
|
||||
bind(list, &a);
|
||||
a = action_new(action_desktop);
|
||||
a->data.desktop.desk = 2;
|
||||
kbind(list, a);
|
||||
|
||||
list->data = "C-4";
|
||||
a.action = Action_Desktop;
|
||||
keyaction_set_uint(&a, 0, 3);
|
||||
keyaction_set_none(&a, 1);
|
||||
bind(list, &a);
|
||||
a = action_new(action_desktop);
|
||||
a->data.desktop.desk = 3;
|
||||
kbind(list, a);
|
||||
|
||||
list->data = "C-space";
|
||||
a.action = Action_Execute;
|
||||
keyaction_set_string(&a, 0, "xterm");
|
||||
keyaction_set_none(&a, 1);
|
||||
bind(list, &a);
|
||||
a = action_new(action_execute);
|
||||
a->data.execute.path = g_strdup("xterm");
|
||||
kbind(list, a);
|
||||
}
|
||||
|
||||
void plugin_startup()
|
||||
|
@ -188,6 +180,10 @@ void plugin_startup()
|
|||
void plugin_shutdown()
|
||||
{
|
||||
dispatch_register(0, (EventHandler)press, NULL);
|
||||
clearall();
|
||||
|
||||
grab_keys(FALSE);
|
||||
tree_destroy(firstnode);
|
||||
firstnode = NULL;
|
||||
grab_keys(TRUE);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
#ifndef __plugin_keyboard_keybaord_h
|
||||
#define __plugin_keyboard_keybaord_h
|
||||
|
||||
#include "keyaction.h"
|
||||
#include <glib.h>
|
||||
|
||||
#include "../../kernel/action.h"
|
||||
|
||||
typedef struct KeyBindingTree {
|
||||
guint state;
|
||||
guint key;
|
||||
GList *keylist;
|
||||
KeyAction action;
|
||||
Action *action;
|
||||
|
||||
/* the next binding in the tree at the same level */
|
||||
struct KeyBindingTree *next_sibling;
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
#include "../../kernel/openbox.h"
|
||||
#include "keyboard.h"
|
||||
#include <glib.h>
|
||||
#include <string.h>
|
||||
|
||||
guint keyboard_translate_modifier(char *str)
|
||||
static guint translate_modifier(char *str)
|
||||
{
|
||||
if (!strcmp("Mod1", str) || !strcmp("A", str)) return Mod1Mask;
|
||||
else if (!strcmp("Mod2", str)) return Mod2Mask;
|
||||
|
@ -36,7 +35,7 @@ gboolean translate_key(char *str, guint *state, guint *keycode)
|
|||
/* figure out the mod mask */
|
||||
*state = 0;
|
||||
for (i = 0; parsed[i] != l; ++i) {
|
||||
guint m = keyboard_translate_modifier(parsed[i]);
|
||||
guint m = translate_modifier(parsed[i]);
|
||||
if (!m) goto translation_fail;
|
||||
*state |= m;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
#include <glib.h>
|
||||
|
||||
guint translate_modifier(char *str);
|
||||
gboolean translate_key(char *str, guint *state, guint *keycode);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include "keyboard.h"
|
||||
#include "translate.h"
|
||||
#include "keyaction.h"
|
||||
#include <glib.h>
|
||||
|
||||
void tree_destroy(KeyBindingTree *tree)
|
||||
|
@ -15,7 +14,7 @@ void tree_destroy(KeyBindingTree *tree)
|
|||
for (it = tree->keylist; it != NULL; it = it->next)
|
||||
g_free(it->data);
|
||||
g_list_free(tree->keylist);
|
||||
keyaction_free(&tree->action);
|
||||
action_free(tree->action);
|
||||
}
|
||||
g_free(tree);
|
||||
tree = c;
|
||||
|
|
|
@ -4,3 +4,4 @@ Makefile
|
|||
Makefile.in
|
||||
.libs
|
||||
.deps
|
||||
translate.lo
|
||||
|
|
|
@ -7,9 +7,9 @@ CPPFLAGS=$(XFT_CFLAGS) $(GLIB_CFLAGS) @CPPFLAGS@ \
|
|||
plugin_LTLIBRARIES=mouse.la
|
||||
|
||||
mouse_la_LDFLAGS=-module -avoid-version
|
||||
mouse_la_SOURCES=mouse.c
|
||||
mouse_la_SOURCES=mouse.c translate.c
|
||||
|
||||
noinst_HEADERS=
|
||||
noinst_HEADERS=mouse.h translate.h
|
||||
|
||||
MAINTAINERCLEANFILES= Makefile.in
|
||||
|
||||
|
|
|
@ -1,29 +1,385 @@
|
|||
#include "../../kernel/openbox.h"
|
||||
#include "../../kernel/dispatch.h"
|
||||
#include "../../kernel/action.h"
|
||||
#include "../../kernel/client.h"
|
||||
#include "../../kernel/frame.h"
|
||||
#include "../../kernel/engine.h"
|
||||
#include "translate.h"
|
||||
#include "mouse.h"
|
||||
#include <glib.h>
|
||||
|
||||
void my_powerful_function() {}
|
||||
/* GData of GSList*s of PointerBinding*s. */
|
||||
static GData *bound_contexts;
|
||||
|
||||
struct foreach_grab_temp {
|
||||
Client *client;
|
||||
gboolean grab;
|
||||
};
|
||||
|
||||
static void grab_button(Client *client, guint state, guint button,
|
||||
GQuark context, gboolean grab)
|
||||
{
|
||||
Window win;
|
||||
int mode = GrabModeAsync;
|
||||
unsigned int mask;
|
||||
|
||||
if (context == g_quark_try_string("frame")) {
|
||||
win = client->frame->window;
|
||||
mask = ButtonPressMask | ButtonMotionMask | ButtonReleaseMask;
|
||||
} else if (context == g_quark_try_string("client")) {
|
||||
win = client->frame->plate;
|
||||
mode = GrabModeSync; /* this is handled in pointer_event */
|
||||
mask = ButtonPressMask; /* can't catch more than this with Sync mode
|
||||
the release event is manufactured in
|
||||
pointer_fire */
|
||||
} else return;
|
||||
|
||||
if (grab)
|
||||
/* XXX grab all lock keys */
|
||||
XGrabButton(ob_display, button, state, win, FALSE, mask, mode,
|
||||
GrabModeAsync, None, None);
|
||||
else
|
||||
/* XXX ungrab all lock keys */
|
||||
XUngrabButton(ob_display, button, state, win);
|
||||
}
|
||||
|
||||
static void foreach_grab(GQuark key, gpointer data, gpointer user_data)
|
||||
{
|
||||
struct foreach_grab_temp *d = user_data;
|
||||
GSList *it;
|
||||
for (it = data; it != NULL; it = it->next) {
|
||||
MouseBinding *b = it->data;
|
||||
grab_button(d->client, b->state, b->button, key, d->grab);
|
||||
}
|
||||
}
|
||||
|
||||
static void grab_for_client(Client *client, gboolean grab)
|
||||
{
|
||||
struct foreach_grab_temp bt;
|
||||
bt.client = client;
|
||||
bt.grab = grab;
|
||||
g_datalist_foreach(&bound_contexts, foreach_grab, &bt);
|
||||
}
|
||||
|
||||
static void grab_all_clients(gboolean grab)
|
||||
{
|
||||
GSList *it;
|
||||
|
||||
for (it = client_list; it != NULL; it = it->next)
|
||||
grab_for_client(it->data, grab);
|
||||
}
|
||||
|
||||
static void foreach_clear(GQuark key, gpointer data, gpointer user_data)
|
||||
{
|
||||
GSList *it;
|
||||
user_data = user_data;
|
||||
for (it = data; it != NULL; it = it->next) {
|
||||
int i;
|
||||
|
||||
MouseBinding *b = it->data;
|
||||
for (i = 0; i < NUM_MOUSEACTION; ++i)
|
||||
action_free(b->action[i]);
|
||||
g_free(b);
|
||||
}
|
||||
g_slist_free(data);
|
||||
}
|
||||
|
||||
static void fire_button(MouseAction a, GQuark context, Client *c, guint state,
|
||||
guint button)
|
||||
{
|
||||
GSList *it;
|
||||
MouseBinding *b;
|
||||
|
||||
for (it = g_datalist_id_get_data(&bound_contexts, context);
|
||||
it != NULL; it = it->next) {
|
||||
b = it->data;
|
||||
if (b->state == state && b->button == button)
|
||||
break;
|
||||
}
|
||||
/* if not bound, then nothing to do! */
|
||||
if (it == NULL) return;
|
||||
|
||||
if (b->action[a] != NULL && b->action[a]->func != NULL) {
|
||||
b->action[a]->data.any.c = c;
|
||||
|
||||
g_assert(!(b->action[a]->func == action_move ||
|
||||
b->action[a]->func == action_resize));
|
||||
|
||||
b->action[a]->func(&b->action[a]->data);
|
||||
}
|
||||
}
|
||||
|
||||
/* corner should be the opposite corner of the window in which the pointer
|
||||
clicked, Corner_TopLeft if a good default if there is no client */
|
||||
static void fire_motion(MouseAction a, GQuark context, Client *c, guint state,
|
||||
guint button, int cx, int cy, int cw, int ch,
|
||||
int dx, int dy, gboolean final, Corner corner)
|
||||
{
|
||||
GSList *it;
|
||||
MouseBinding *b;
|
||||
|
||||
for (it = g_datalist_id_get_data(&bound_contexts, context);
|
||||
it != NULL; it = it->next) {
|
||||
b = it->data;
|
||||
if (b->state == state && b->button == button)
|
||||
break;
|
||||
}
|
||||
/* if not bound, then nothing to do! */
|
||||
if (it == NULL) return;
|
||||
|
||||
if (b->action[a] != NULL && b->action[a]->func != NULL) {
|
||||
b->action[a]->data.any.c = c;
|
||||
|
||||
if (b->action[a]->func == action_move) {
|
||||
b->action[a]->data.move.x = cx + dx;
|
||||
b->action[a]->data.move.y = cy + dy;
|
||||
b->action[a]->data.move.final = final;
|
||||
} else if (b->action[a]->func == action_resize) {
|
||||
b->action[a]->data.resize.corner = corner;
|
||||
switch (corner) {
|
||||
case Corner_TopLeft:
|
||||
b->action[a]->data.resize.x = cw + dx;
|
||||
b->action[a]->data.resize.y = ch + dy;
|
||||
break;
|
||||
case Corner_TopRight:
|
||||
b->action[a]->data.resize.x = cw - dx;
|
||||
b->action[a]->data.resize.y = ch + dy;
|
||||
break;
|
||||
case Corner_BottomLeft:
|
||||
b->action[a]->data.resize.x = cw + dx;
|
||||
b->action[a]->data.resize.y = ch - dy;
|
||||
break;
|
||||
case Corner_BottomRight:
|
||||
b->action[a]->data.resize.x = cw - dx;
|
||||
b->action[a]->data.resize.y = ch - dy;
|
||||
break;
|
||||
}
|
||||
b->action[a]->data.resize.final = final;
|
||||
}
|
||||
b->action[a]->func(&b->action[a]->data);
|
||||
}
|
||||
}
|
||||
|
||||
static Corner pick_corner(int x, int y, int cx, int cy, int cw, int ch)
|
||||
{
|
||||
if (x - cx < cw / 2) {
|
||||
if (y - cy < ch / 2)
|
||||
return Corner_BottomRight;
|
||||
else
|
||||
return Corner_TopRight;
|
||||
} else {
|
||||
if (y - cy < ch / 2)
|
||||
return Corner_BottomLeft;
|
||||
else
|
||||
return Corner_TopLeft;
|
||||
}
|
||||
}
|
||||
|
||||
static void event(ObEvent *e, void *foo)
|
||||
{
|
||||
static Time ltime;
|
||||
static int px, py, cx, cy, cw, ch, dx, dy;
|
||||
static guint button = 0, lbutton = 0;
|
||||
static gboolean drag = FALSE;
|
||||
static Corner corner = Corner_TopLeft;
|
||||
gboolean click = FALSE;
|
||||
gboolean dclick = FALSE;
|
||||
|
||||
switch (e->type) {
|
||||
case Event_Client_Mapped:
|
||||
grab_for_client(e->data.c.client, TRUE);
|
||||
break;
|
||||
|
||||
case Event_Client_Destroy:
|
||||
grab_for_client(e->data.c.client, FALSE);
|
||||
break;
|
||||
|
||||
case Event_X_ButtonPress:
|
||||
if (!button) {
|
||||
if (e->data.x.client == NULL)
|
||||
corner = Corner_TopLeft;
|
||||
else {
|
||||
cx = e->data.x.client->frame->area.x;
|
||||
cy = e->data.x.client->frame->area.y;
|
||||
cw = e->data.x.client->frame->area.width;
|
||||
ch = e->data.x.client->frame->area.height;
|
||||
px = e->data.x.e->xbutton.x_root;
|
||||
py = e->data.x.e->xbutton.y_root;
|
||||
corner = pick_corner(px, py, cx, cy, cw, ch);
|
||||
button = e->data.x.e->xbutton.button;
|
||||
}
|
||||
}
|
||||
fire_button(MouseAction_Press,
|
||||
engine_get_context(e->data.x.client,
|
||||
e->data.x.e->xbutton.window),
|
||||
e->data.x.client, e->data.x.e->xbutton.state,
|
||||
e->data.x.e->xbutton.button);
|
||||
break;
|
||||
|
||||
case Event_X_ButtonRelease:
|
||||
if (e->data.x.e->xbutton.button == button) {
|
||||
/* end drags */
|
||||
if (drag) {
|
||||
fire_motion(MouseAction_Motion,
|
||||
engine_get_context(e->data.x.client,
|
||||
e->data.x.e->xbutton.window),
|
||||
e->data.x.client, e->data.x.e->xbutton.state,
|
||||
e->data.x.e->xbutton.button,
|
||||
cx, cy, cw, ch, dx, dy, TRUE, corner);
|
||||
}
|
||||
|
||||
/* clicks are only valid if its released over the window */
|
||||
if (e->data.x.e->xbutton.x >= 0 && e->data.x.e->xbutton.y >= 0) {
|
||||
int junk;
|
||||
Window wjunk;
|
||||
guint ujunk, w, h;
|
||||
XGetGeometry(ob_display, e->data.x.e->xbutton.window,
|
||||
&wjunk, &junk, &junk, &w, &h, &ujunk, &ujunk);
|
||||
if (e->data.x.e->xbutton.x < (signed)w &&
|
||||
e->data.x.e->xbutton.y < (signed)h) {
|
||||
click =TRUE;
|
||||
/* double clicks happen if there were 2 in a row! */
|
||||
if (lbutton == button &&
|
||||
e->data.x.e->xbutton.time - 300 <= ltime)
|
||||
dclick = TRUE;
|
||||
}
|
||||
lbutton = button;
|
||||
} else
|
||||
lbutton = 0;
|
||||
|
||||
button = 0;
|
||||
ltime = e->data.x.e->xbutton.time;
|
||||
}
|
||||
fire_button(MouseAction_Press,
|
||||
engine_get_context(e->data.x.client,
|
||||
e->data.x.e->xbutton.window),
|
||||
e->data.x.client, e->data.x.e->xbutton.state,
|
||||
e->data.x.e->xbutton.button);
|
||||
if (click)
|
||||
fire_button(MouseAction_Click,
|
||||
engine_get_context(e->data.x.client,
|
||||
e->data.x.e->xbutton.window),
|
||||
e->data.x.client, e->data.x.e->xbutton.state,
|
||||
e->data.x.e->xbutton.button);
|
||||
if (dclick)
|
||||
fire_button(MouseAction_DClick,
|
||||
engine_get_context(e->data.x.client,
|
||||
e->data.x.e->xbutton.window),
|
||||
e->data.x.client, e->data.x.e->xbutton.state,
|
||||
e->data.x.e->xbutton.button);
|
||||
break;
|
||||
|
||||
case Event_X_MotionNotify:
|
||||
if (button) {
|
||||
drag = TRUE;
|
||||
dx = e->data.x.e->xmotion.x_root - px;
|
||||
dy = e->data.x.e->xmotion.y_root - py;
|
||||
fire_motion(MouseAction_Motion,
|
||||
engine_get_context(e->data.x.client,
|
||||
e->data.x.e->xbutton.window),
|
||||
e->data.x.client, e->data.x.e->xmotion.state,
|
||||
button, cx, cy, cw, ch, dx, dy, FALSE, corner);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean mbind(char *buttonstr, char *contextstr, MouseAction mact,
|
||||
Action *action)
|
||||
{
|
||||
guint state, button;
|
||||
GQuark context;
|
||||
MouseBinding *b;
|
||||
GSList *it;
|
||||
guint i;
|
||||
|
||||
if (!translate_button(buttonstr, &state, &button)) {
|
||||
g_warning("invalid button");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
context = g_quark_try_string(contextstr);
|
||||
if (!context) {
|
||||
g_warning("invalid context");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (it = g_datalist_id_get_data(&bound_contexts, context);
|
||||
it != NULL; it = it->next){
|
||||
b = it->data;
|
||||
if (b->state == state && b->button == button) {
|
||||
/* already bound */
|
||||
if (b->action[mact] != NULL) {
|
||||
g_warning("duplicate binding");
|
||||
return FALSE;
|
||||
}
|
||||
b->action[mact] = action;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
grab_all_clients(FALSE);
|
||||
|
||||
/* add the binding */
|
||||
b = g_new(MouseBinding, 1);
|
||||
b->state = state;
|
||||
b->button = button;
|
||||
for (i = 0; i < NUM_MOUSEACTION; ++i)
|
||||
if (i != mact)
|
||||
b->action[i] = NULL;
|
||||
b->action[mact] = action;
|
||||
g_datalist_id_set_data(&bound_contexts, context,
|
||||
g_slist_append(g_datalist_id_get_data(&bound_contexts, context), b));
|
||||
|
||||
grab_all_clients(TRUE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void binddef()
|
||||
{
|
||||
Action *a;
|
||||
|
||||
/* When creating an Action struct, all of the data elements in the
|
||||
appropriate struct need to be set, except the Client*, which will be set
|
||||
at call-time when then action function is used.
|
||||
|
||||
For action_move and action_resize, the 'x', 'y', and 'final' data
|
||||
elements should not be set, as they are set at call-time.
|
||||
*/
|
||||
|
||||
a = action_new(action_move);
|
||||
mbind("1", "titlebar", MouseAction_Motion, a);
|
||||
a = action_new(action_move);
|
||||
mbind("1", "handle", MouseAction_Motion, a);
|
||||
a = action_new(action_move);
|
||||
mbind("A-1", "frame", MouseAction_Motion, a);
|
||||
|
||||
a = action_new(action_resize);
|
||||
mbind("1", "blcorner", MouseAction_Motion, a);
|
||||
a = action_new(action_resize);
|
||||
mbind("1", "brcorner", MouseAction_Motion, a);
|
||||
a = action_new(action_resize);
|
||||
mbind("A-3", "frame", MouseAction_Motion, a);
|
||||
}
|
||||
|
||||
void plugin_startup()
|
||||
{
|
||||
dispatch_register(Event_X_ButtonPress | Event_X_ButtonRelease |
|
||||
dispatch_register(Event_Client_Mapped | Event_Client_Destroy |
|
||||
Event_X_ButtonPress | Event_X_ButtonRelease |
|
||||
Event_X_MotionNotify, (EventHandler)event, NULL);
|
||||
|
||||
/* XXX parse a config */
|
||||
binddef();
|
||||
}
|
||||
|
||||
void plugin_shutdown()
|
||||
{
|
||||
dispatch_register(0, (EventHandler)event, NULL);
|
||||
|
||||
grab_all_clients(FALSE);
|
||||
g_datalist_foreach(&bound_contexts, foreach_clear, NULL);
|
||||
}
|
||||
|
|
21
plugins/mouse/mouse.h
Normal file
21
plugins/mouse/mouse.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
#ifndef __plugin_mouse_mouse_h
|
||||
#define __plugin_mouse_mouse_h
|
||||
|
||||
#include "../../kernel/action.h"
|
||||
|
||||
typedef enum {
|
||||
MouseAction_Press,
|
||||
MouseAction_Release,
|
||||
MouseAction_Click,
|
||||
MouseAction_DClick,
|
||||
MouseAction_Motion,
|
||||
NUM_MOUSEACTION
|
||||
} MouseAction;
|
||||
|
||||
typedef struct {
|
||||
guint state;
|
||||
guint button;
|
||||
Action *action[NUM_MOUSEACTION];
|
||||
} MouseBinding;
|
||||
|
||||
#endif
|
55
plugins/mouse/translate.c
Normal file
55
plugins/mouse/translate.c
Normal file
|
@ -0,0 +1,55 @@
|
|||
#include "../../kernel/openbox.h"
|
||||
#include <glib.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static guint translate_modifier(char *str)
|
||||
{
|
||||
if (!strcmp("Mod1", str) || !strcmp("A", str)) return Mod1Mask;
|
||||
else if (!strcmp("Mod2", str)) return Mod2Mask;
|
||||
else if (!strcmp("Mod3", str)) return Mod3Mask;
|
||||
else if (!strcmp("Mod4", str) || !strcmp("W", str)) return Mod4Mask;
|
||||
else if (!strcmp("Mod5", str)) return Mod5Mask;
|
||||
else if (!strcmp("C", str)) return ControlMask;
|
||||
else if (!strcmp("S", str)) return ShiftMask;
|
||||
g_warning("Invalid modifier '%s' in binding.", str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
gboolean translate_button(char *str, guint *state, guint *button)
|
||||
{
|
||||
char **parsed;
|
||||
char *l;
|
||||
int i;
|
||||
gboolean ret = FALSE;
|
||||
|
||||
parsed = g_strsplit(str, "-", -1);
|
||||
|
||||
/* first, find the button (last token) */
|
||||
l = NULL;
|
||||
for (i = 0; parsed[i] != NULL; ++i)
|
||||
l = parsed[i];
|
||||
if (l == NULL)
|
||||
goto translation_fail;
|
||||
|
||||
/* figure out the mod mask */
|
||||
*state = 0;
|
||||
for (i = 0; parsed[i] != l; ++i) {
|
||||
guint m = translate_modifier(parsed[i]);
|
||||
if (!m) goto translation_fail;
|
||||
*state |= m;
|
||||
}
|
||||
|
||||
/* figure out the button */
|
||||
*button = atoi(l);
|
||||
if (!*button) {
|
||||
g_warning("Invalid button '%s' in pointer binding.", l);
|
||||
goto translation_fail;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
translation_fail:
|
||||
g_strfreev(parsed);
|
||||
return ret;
|
||||
}
|
8
plugins/mouse/translate.h
Normal file
8
plugins/mouse/translate.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#ifndef __plugin_mouse_translate_h
|
||||
#define __plugin_mouse_translate_h
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
gboolean translate_button(char *str, guint *state, guint *keycode);
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue