move the keyboard and mouse plugins into the kernel for mucho sexiness.

make workspace changing a grabbed/interactive process like focus cycling is, with the popup and all.
this is some hot shit.
This commit is contained in:
Dana Jansens 2003-08-12 07:26:16 +00:00
parent cb49f853c9
commit c90da6da78
29 changed files with 1342 additions and 514 deletions

View file

@ -1,3 +1,64 @@
2003-08-12 xor@zed.orodu.net <xor@zed>
* kernel/event.c:
keep event_lasttime at the last time an event has come in so far, don't regress when events come out of order. props to shrimpx for this patch.
2003-08-11 woodblock <woodblock@zed>
* kernel/menu.c, kernel/menu.h, kernel/menu_render.c, plugins/menu/fifo_menu.c, plugins/menu/timed_menu.c, render/theme.c, render/theme.h:
Some fixes and new bugs. Someone else can do the menus because it is
clear no one gives a fuck what I think and no one else wants a window
manager that doesn't suck the same balls as every other window manager.
2003-08-10 xor@zed.orodu.net <xor@zed>
* kernel/client.c:
save the frame decorations in client_configure_full before causing the fake frame adjust, since that loses its old value.
2003-08-10 xor@zed.orodu.net <xor@zed>
* framerender.c:
clear the window after setting the background color, this isnt implicit
2003-08-09 xor@zed.orodu.net <xor@zed>
* focus.c, popup.c, popup.h, screen.c, timer.c, timer.h:
changes to the timer api, pass the timer to the callback function.
add a desktop-switch popup with the desktop's name
2003-08-07 woodblock <woodblock@zed>
* event.c:
Fix lock up when not using a session manager and doing fd management.
2003-08-05 xor@zed.orodu.net <xor@zed>
* screen.c: dont ignore topleft layouts
* frame.c:
dont map the tl/tr invisible grips when the grip decors are turned off
* client.c, frame.c, frame.h, framerender.c:
a couple frame layout bugfixes hidden inside all this.. wee
fixes for maximizing windows:
- when you toggledecor, it will reconfigure once, but the new constraints from the decor changes would not be in effect when the window was resized to the contranits. fixed by calling frame_adjust_area first thing ni client_configure_fulll with fake=TRUE which will recalc all the frame geometry without resizing/redrawing anything in the frame. this way the decor can take effect in the geometries.
- when maxed horizontally, make the client fill the screen, but dont do this by just making it wider than the screen, fit it to the screen and adjust the titlebar/handle as appropriate to keep it all on the screen.
- when maxed horizontally and vertically, remove the handle from the decorations
* client.c:
when setting up decor on a window, it needs to reconfigure twice if the decor changes, cuz the constraints need the new frame sizes to work right
* moveresize.c:
make the position dislpayed in the moving popup offset by the top/left struts so that 0,0 is inside teh struts not neccessarily at the screen edge
2003-08-03 xor@zed.orodu.net <xor@zed>
* client.c, config.c, config.h, moveresize.c:
kill non-opaque move/resize
add an option for redrawing/resizing the client window while resizing, when disabled the client is not touched until the resize is complete.
* framerender.c: give the plate the same background color as its border
2003-08-03 xor@zed.orodu.net <xor@zed> 2003-08-03 xor@zed.orodu.net <xor@zed>
* data/rc3, kernel/client.c, kernel/config.c, kernel/config.h, kernel/moveresize.c: * data/rc3, kernel/client.c, kernel/config.c, kernel/config.h, kernel/moveresize.c:

View file

@ -28,8 +28,6 @@ bin_PROGRAMS = \
plugin_LTLIBRARIES = \ plugin_LTLIBRARIES = \
plugins/resistance/resistance.la \ plugins/resistance/resistance.la \
plugins/placement/placement.la \ plugins/placement/placement.la \
plugins/mouse/mouse.la \
plugins/keyboard/keyboard.la \
plugins/menu/timed_menu.la \ plugins/menu/timed_menu.la \
plugins/menu/fifo_menu.la \ plugins/menu/fifo_menu.la \
plugins/menu/client_menu.la \ plugins/menu/client_menu.la \
@ -157,10 +155,16 @@ kernel_openbox_SOURCES = \
kernel/grab.h \ kernel/grab.h \
kernel/group.c \ kernel/group.c \
kernel/group.h \ kernel/group.h \
kernel/keyboard.c \
kernel/keyboard.h \
kernel/keytree.c \
kernel/keytree.h \
kernel/menu.c \ kernel/menu.c \
kernel/menu.h \ kernel/menu.h \
kernel/menu_render.c \ kernel/menu_render.c \
kernel/misc.h \ kernel/misc.h \
kernel/mouse.c \
kernel/mouse.h \
kernel/moveresize.c \ kernel/moveresize.c \
kernel/moveresize.h \ kernel/moveresize.h \
kernel/mwm.h \ kernel/mwm.h \
@ -182,6 +186,8 @@ kernel_openbox_SOURCES = \
kernel/startup.h \ kernel/startup.h \
kernel/timer.c \ kernel/timer.c \
kernel/timer.h \ kernel/timer.h \
kernel/translate.c \
kernel/translate.h \
kernel/window.c \ kernel/window.c \
kernel/window.h \ kernel/window.h \
kernel/xerror.c \ kernel/xerror.c \
@ -238,44 +244,6 @@ plugins_placement_placement_la_SOURCES = \
plugins/placement/history.c \ plugins/placement/history.c \
plugins/placement/history.h plugins/placement/history.h
## plugins/mouse ##
plugins_mouse_mouse_la_CPPFLAGS = \
$(XFT_CFLAGS) \
$(GLIB_CFLAGS) \
$(LIBSN_CFLAGS) \
$(XML_CFLAGS) \
-DPLUGINDIR=\"$(plugindir)\" \
-DG_LOG_DOMAIN=\"Plugin-Mouse\"
plugins_mouse_mouse_la_LDFLAGS = \
-module \
-avoid-version
plugins_mouse_mouse_la_SOURCES = \
plugins/mouse/mouse.c \
plugins/mouse/mouse.h \
plugins/mouse/translate.c \
plugins/mouse/translate.h
## plugins/mouse ##
plugins_keyboard_keyboard_la_CPPFLAGS = \
$(XFT_CFLAGS) \
$(GLIB_CFLAGS) \
$(LIBSN_CFLAGS) \
$(XML_CFLAGS) \
-DPLUGINDIR=\"$(plugindir)\" \
-DG_LOG_DOMAIN=\"Plugin-Keyboard\"
plugins_keyboard_keyboard_la_LDFLAGS = \
-module \
-avoid-version
plugins_keyboard_keyboard_la_SOURCES = \
plugins/keyboard/keyboard.c \
plugins/keyboard/keyboard.h \
plugins/keyboard/tree.c \
plugins/keyboard/tree.h \
plugins/keyboard/translate.c \
plugins/keyboard/translate.h
## plugins/menu ## ## plugins/menu ##
plugins_menu_timed_menu_la_CPPFLAGS = \ plugins_menu_timed_menu_la_CPPFLAGS = \

View file

@ -29,3 +29,6 @@ xerror.lo
.deps .deps
openbox openbox
.dirstamp .dirstamp
keyboard.lo
mouse.lo
keytree.lo

View file

@ -16,18 +16,18 @@
typedef struct ActionString { typedef struct ActionString {
char *name; char *name;
void (*func)(union ActionData *); void (*func)(union ActionData *);
void (*setup)(Action *); void (*setup)(ObAction *);
} ActionString; } ActionString;
Action *action_new(void (*func)(union ActionData *data)) ObAction *action_new(void (*func)(union ActionData *data))
{ {
Action *a = g_new0(Action, 1); ObAction *a = g_new0(ObAction, 1);
a->func = func; a->func = func;
return a; return a;
} }
void action_free(Action *a) void action_free(ObAction *a)
{ {
if (a == NULL) return; if (a == NULL) return;
@ -40,137 +40,209 @@ void action_free(Action *a)
g_free(a); g_free(a);
} }
void setup_action_directional_focus_north(Action *a) void setup_action_directional_focus_north(ObAction *a)
{ {
a->data.diraction.direction = OB_DIRECTION_NORTH; a->data.diraction.direction = OB_DIRECTION_NORTH;
} }
void setup_action_directional_focus_east(Action *a) void setup_action_directional_focus_east(ObAction *a)
{ {
a->data.diraction.direction = OB_DIRECTION_EAST; a->data.diraction.direction = OB_DIRECTION_EAST;
} }
void setup_action_directional_focus_south(Action *a) void setup_action_directional_focus_south(ObAction *a)
{ {
a->data.diraction.direction = OB_DIRECTION_SOUTH; a->data.diraction.direction = OB_DIRECTION_SOUTH;
} }
void setup_action_directional_focus_west(Action *a) void setup_action_directional_focus_west(ObAction *a)
{ {
a->data.diraction.direction = OB_DIRECTION_WEST; a->data.diraction.direction = OB_DIRECTION_WEST;
} }
void setup_action_directional_focus_northeast(Action *a) void setup_action_directional_focus_northeast(ObAction *a)
{ {
a->data.diraction.direction = OB_DIRECTION_NORTHEAST; a->data.diraction.direction = OB_DIRECTION_NORTHEAST;
} }
void setup_action_directional_focus_southeast(Action *a) void setup_action_directional_focus_southeast(ObAction *a)
{ {
a->data.diraction.direction = OB_DIRECTION_SOUTHEAST; a->data.diraction.direction = OB_DIRECTION_SOUTHEAST;
} }
void setup_action_directional_focus_southwest(Action *a) void setup_action_directional_focus_southwest(ObAction *a)
{ {
a->data.diraction.direction = OB_DIRECTION_SOUTHWEST; a->data.diraction.direction = OB_DIRECTION_SOUTHWEST;
} }
void setup_action_directional_focus_northwest(Action *a) void setup_action_directional_focus_northwest(ObAction *a)
{ {
a->data.diraction.direction = OB_DIRECTION_NORTHWEST; a->data.diraction.direction = OB_DIRECTION_NORTHWEST;
} }
void setup_action_send_to_desktop(Action *a) void setup_action_send_to_desktop(ObAction *a)
{ {
a->data.sendto.follow = TRUE;
} }
void setup_action_send_to_desktop_direction(Action *a) void setup_action_send_to_desktop_prev(ObAction *a)
{ {
a->data.sendtodir.dir = OB_DIRECTION_WEST;
a->data.sendtodir.linear = TRUE;
a->data.sendtodir.wrap = TRUE; a->data.sendtodir.wrap = TRUE;
a->data.sendtodir.follow = TRUE;
} }
void setup_action_desktop_direction(Action *a) void setup_action_send_to_desktop_next(ObAction *a)
{ {
a->data.sendtodir.dir = OB_DIRECTION_EAST;
a->data.sendtodir.linear = TRUE;
a->data.sendtodir.wrap = TRUE;
}
void setup_action_send_to_desktop_left(ObAction *a)
{
a->data.sendtodir.dir = OB_DIRECTION_WEST;
a->data.sendtodir.linear = FALSE;
a->data.sendtodir.wrap = TRUE;
}
void setup_action_send_to_desktop_right(ObAction *a)
{
a->data.sendtodir.dir = OB_DIRECTION_EAST;
a->data.sendtodir.linear = FALSE;
a->data.sendtodir.wrap = TRUE;
}
void setup_action_send_to_desktop_up(ObAction *a)
{
a->data.sendtodir.dir = OB_DIRECTION_NORTH;
a->data.sendtodir.linear = FALSE;
a->data.sendtodir.wrap = TRUE;
}
void setup_action_send_to_desktop_down(ObAction *a)
{
a->data.sendtodir.dir = OB_DIRECTION_SOUTH;
a->data.sendtodir.linear = FALSE;
a->data.sendtodir.wrap = TRUE;
}
void setup_action_desktop_prev(ObAction *a)
{
a->data.desktopdir.dir = OB_DIRECTION_WEST;
a->data.desktopdir.linear = TRUE;
a->data.desktopdir.wrap = TRUE; a->data.desktopdir.wrap = TRUE;
} }
void setup_action_move_keyboard(Action *a) void setup_action_desktop_next(ObAction *a)
{
a->data.desktopdir.dir = OB_DIRECTION_EAST;
a->data.desktopdir.linear = TRUE;
a->data.desktopdir.wrap = TRUE;
}
void setup_action_desktop_left(ObAction *a)
{
a->data.desktopdir.dir = OB_DIRECTION_WEST;
a->data.desktopdir.linear = FALSE;
a->data.desktopdir.wrap = TRUE;
}
void setup_action_desktop_right(ObAction *a)
{
a->data.desktopdir.dir = OB_DIRECTION_EAST;
a->data.desktopdir.linear = FALSE;
a->data.desktopdir.wrap = TRUE;
}
void setup_action_desktop_up(ObAction *a)
{
a->data.desktopdir.dir = OB_DIRECTION_NORTH;
a->data.desktopdir.linear = FALSE;
a->data.desktopdir.wrap = TRUE;
}
void setup_action_desktop_down(ObAction *a)
{
a->data.desktopdir.dir = OB_DIRECTION_SOUTH;
a->data.desktopdir.linear = FALSE;
a->data.desktopdir.wrap = TRUE;
}
void setup_action_move_keyboard(ObAction *a)
{ {
a->data.moveresize.corner = prop_atoms.net_wm_moveresize_move_keyboard; a->data.moveresize.corner = prop_atoms.net_wm_moveresize_move_keyboard;
} }
void setup_action_move(Action *a) void setup_action_move(ObAction *a)
{ {
a->data.moveresize.corner = prop_atoms.net_wm_moveresize_move; a->data.moveresize.corner = prop_atoms.net_wm_moveresize_move;
} }
void setup_action_resize(Action *a) void setup_action_resize(ObAction *a)
{ {
a->data.moveresize.corner = prop_atoms.net_wm_moveresize_size_topleft; a->data.moveresize.corner = prop_atoms.net_wm_moveresize_size_topleft;
} }
void setup_action_resize_keyboard(Action *a) void setup_action_resize_keyboard(ObAction *a)
{ {
a->data.moveresize.corner = prop_atoms.net_wm_moveresize_size_keyboard; a->data.moveresize.corner = prop_atoms.net_wm_moveresize_size_keyboard;
} }
void setup_action_cycle_windows_linear_next(Action *a) void setup_action_cycle_windows_linear_next(ObAction *a)
{ {
a->data.cycle.linear = TRUE; a->data.cycle.linear = TRUE;
a->data.cycle.forward = TRUE; a->data.cycle.forward = TRUE;
} }
void setup_action_cycle_windows_linear_previous(Action *a) void setup_action_cycle_windows_linear_previous(ObAction *a)
{ {
a->data.cycle.linear = TRUE; a->data.cycle.linear = TRUE;
a->data.cycle.forward = FALSE; a->data.cycle.forward = FALSE;
} }
void setup_action_cycle_windows_next(Action *a) void setup_action_cycle_windows_next(ObAction *a)
{ {
a->data.cycle.linear = FALSE; a->data.cycle.linear = FALSE;
a->data.cycle.forward = TRUE; a->data.cycle.forward = TRUE;
} }
void setup_action_cycle_windows_previous(Action *a) void setup_action_cycle_windows_previous(ObAction *a)
{ {
a->data.cycle.linear = FALSE; a->data.cycle.linear = FALSE;
a->data.cycle.forward = FALSE; a->data.cycle.forward = FALSE;
} }
void setup_action_movetoedge_north(Action *a) void setup_action_movetoedge_north(ObAction *a)
{ {
a->data.diraction.direction = OB_DIRECTION_NORTH; a->data.diraction.direction = OB_DIRECTION_NORTH;
} }
void setup_action_movetoedge_south(Action *a) void setup_action_movetoedge_south(ObAction *a)
{ {
a->data.diraction.direction = OB_DIRECTION_SOUTH; a->data.diraction.direction = OB_DIRECTION_SOUTH;
} }
void setup_action_movetoedge_east(Action *a) void setup_action_movetoedge_east(ObAction *a)
{ {
a->data.diraction.direction = OB_DIRECTION_EAST; a->data.diraction.direction = OB_DIRECTION_EAST;
} }
void setup_action_movetoedge_west(Action *a) void setup_action_movetoedge_west(ObAction *a)
{ {
a->data.diraction.direction = OB_DIRECTION_WEST; a->data.diraction.direction = OB_DIRECTION_WEST;
} }
void setup_action_top_layer(Action *a) void setup_action_top_layer(ObAction *a)
{ {
a->data.layer.layer = 1; a->data.layer.layer = 1;
} }
void setup_action_normal_layer(Action *a) void setup_action_normal_layer(ObAction *a)
{ {
a->data.layer.layer = 0; a->data.layer.layer = 0;
} }
void setup_action_bottom_layer(Action *a) void setup_action_bottom_layer(ObAction *a)
{ {
a->data.layer.layer = -1; a->data.layer.layer = -1;
} }
@ -357,50 +429,70 @@ ActionString actionstrings[] =
action_send_to_desktop, action_send_to_desktop,
setup_action_send_to_desktop setup_action_send_to_desktop
}, },
{
"sendtodesktopnext",
action_send_to_desktop_dir,
setup_action_send_to_desktop_next
},
{
"sendtodesktopprevious",
action_send_to_desktop_dir,
setup_action_send_to_desktop_prev
},
{ {
"sendtodesktopright", "sendtodesktopright",
action_send_to_desktop_right, action_send_to_desktop_dir,
setup_action_send_to_desktop_direction setup_action_send_to_desktop_right
}, },
{ {
"sendtodesktopleft", "sendtodesktopleft",
action_send_to_desktop_left, action_send_to_desktop_dir,
setup_action_send_to_desktop_direction setup_action_send_to_desktop_left
}, },
{ {
"sendtodesktopup", "sendtodesktopup",
action_send_to_desktop_up, action_send_to_desktop_dir,
setup_action_send_to_desktop_direction setup_action_send_to_desktop_up
}, },
{ {
"sendtodesktopdown", "sendtodesktopdown",
action_send_to_desktop_down, action_send_to_desktop_dir,
setup_action_send_to_desktop_direction setup_action_send_to_desktop_down
}, },
{ {
"desktop", "desktop",
action_desktop, action_desktop,
NULL NULL
}, },
{
"desktopnext",
action_desktop_dir,
setup_action_desktop_next
},
{
"desktopprevious",
action_desktop_dir,
setup_action_desktop_prev
},
{ {
"desktopright", "desktopright",
action_desktop_right, action_desktop_dir,
setup_action_desktop_direction setup_action_desktop_right
}, },
{ {
"desktopleft", "desktopleft",
action_desktop_left, action_desktop_dir,
setup_action_desktop_direction setup_action_desktop_left
}, },
{ {
"desktopup", "desktopup",
action_desktop_up, action_desktop_dir,
setup_action_desktop_direction setup_action_desktop_up
}, },
{ {
"desktopdown", "desktopdown",
action_desktop_down, action_desktop_dir,
setup_action_desktop_direction setup_action_desktop_down
}, },
{ {
"toggledecorations", "toggledecorations",
@ -529,9 +621,9 @@ ActionString actionstrings[] =
} }
}; };
Action *action_from_string(char *name) ObAction *action_from_string(char *name)
{ {
Action *a = NULL; ObAction *a = NULL;
int i; int i;
for (i = 0; actionstrings[i].name; i++) for (i = 0; actionstrings[i].name; i++)
@ -544,10 +636,10 @@ Action *action_from_string(char *name)
return a; return a;
} }
Action *action_parse(xmlDocPtr doc, xmlNodePtr node) ObAction *action_parse(xmlDocPtr doc, xmlNodePtr node)
{ {
char *actname; char *actname;
Action *act = NULL; ObAction *act = NULL;
xmlNodePtr n; xmlNodePtr n;
if (parse_attr_string("name", node, &actname)) { if (parse_attr_string("name", node, &actname)) {
@ -572,21 +664,13 @@ Action *action_parse(xmlDocPtr doc, xmlNodePtr node)
act->func == action_resize_relative_vert) { act->func == action_resize_relative_vert) {
if ((n = parse_find_node("delta", node->xmlChildrenNode))) if ((n = parse_find_node("delta", node->xmlChildrenNode)))
act->data.relative.delta = parse_int(doc, n); act->data.relative.delta = parse_int(doc, n);
} else if (act->func == action_desktop_right || } else if (act->func == action_desktop_dir) {
act->func == action_desktop_left ||
act->func == action_desktop_up ||
act->func == action_desktop_down) {
if ((n = parse_find_node("wrap", node->xmlChildrenNode))) { if ((n = parse_find_node("wrap", node->xmlChildrenNode))) {
act->data.desktopdir.wrap = parse_bool(doc, n); act->data.desktopdir.wrap = parse_bool(doc, n);
} }
} else if (act->func == action_send_to_desktop_right || } else if (act->func == action_send_to_desktop_dir) {
act->func == action_send_to_desktop_left ||
act->func == action_send_to_desktop_up ||
act->func == action_send_to_desktop_down) {
if ((n = parse_find_node("wrap", node->xmlChildrenNode))) if ((n = parse_find_node("wrap", node->xmlChildrenNode)))
act->data.sendtodir.wrap = parse_bool(doc, n); act->data.sendtodir.wrap = parse_bool(doc, n);
if ((n = parse_find_node("follow", node->xmlChildrenNode)))
act->data.sendtodir.follow = parse_bool(doc, n);
} }
} }
g_free(actname); g_free(actname);
@ -802,8 +886,8 @@ void action_send_to_desktop(union ActionData *data)
if (data->sendto.desk < screen_num_desktops || if (data->sendto.desk < screen_num_desktops ||
data->sendto.desk == DESKTOP_ALL) { data->sendto.desk == DESKTOP_ALL) {
client_set_desktop(c, data->sendto.desk, data->sendto.follow); client_set_desktop(c, data->sendto.desk, TRUE);
if (data->sendto.follow) screen_set_desktop(data->sendto.desk); screen_set_desktop(data->sendto.desk);
} }
} }
@ -814,114 +898,34 @@ void action_desktop(union ActionData *data)
screen_set_desktop(data->desktop.desk); screen_set_desktop(data->desktop.desk);
} }
static void cur_row_col(guint *r, guint *c) void action_desktop_dir(union ActionData *data)
{ {
switch (screen_desktop_layout.orientation) { guint d;
case OB_ORIENTATION_HORZ:
switch (screen_desktop_layout.start_corner) { d = screen_cycle_desktop(data->desktopdir.dir, data->desktopdir.wrap,
case OB_CORNER_TOPLEFT: data->sendtodir.linear,
*r = screen_desktop / screen_desktop_layout.columns; data->desktopdir.final, data->desktopdir.cancel);
*c = screen_desktop % screen_desktop_layout.columns; screen_set_desktop(d);
break;
case OB_CORNER_BOTTOMLEFT:
*r = screen_desktop_layout.rows - 1 -
screen_desktop / screen_desktop_layout.columns;
*c = screen_desktop % screen_desktop_layout.columns;
break;
case OB_CORNER_TOPRIGHT:
*r = screen_desktop / screen_desktop_layout.columns;
*c = screen_desktop_layout.columns - 1 -
screen_desktop % screen_desktop_layout.columns;
break;
case OB_CORNER_BOTTOMRIGHT:
*r = screen_desktop_layout.rows - 1 -
screen_desktop / screen_desktop_layout.columns;
*c = screen_desktop_layout.columns - 1 -
screen_desktop % screen_desktop_layout.columns;
break;
}
break;
case OB_ORIENTATION_VERT:
switch (screen_desktop_layout.start_corner) {
case OB_CORNER_TOPLEFT:
*r = screen_desktop % screen_desktop_layout.rows;
*c = screen_desktop / screen_desktop_layout.rows;
break;
case OB_CORNER_BOTTOMLEFT:
*r = screen_desktop_layout.rows - 1 -
screen_desktop % screen_desktop_layout.rows;
*c = screen_desktop / screen_desktop_layout.rows;
break;
case OB_CORNER_TOPRIGHT:
*r = screen_desktop % screen_desktop_layout.rows;
*c = screen_desktop_layout.columns - 1 -
screen_desktop / screen_desktop_layout.rows;
break;
case OB_CORNER_BOTTOMRIGHT:
*r = screen_desktop_layout.rows - 1 -
screen_desktop % screen_desktop_layout.rows;
*c = screen_desktop_layout.columns - 1 -
screen_desktop / screen_desktop_layout.rows;
break;
}
break;
}
} }
static guint translate_row_col(guint r, guint c) void action_send_to_desktop_dir(union ActionData *data)
{ {
switch (screen_desktop_layout.orientation) { ObClient *c = data->sendtodir.c;
case OB_ORIENTATION_HORZ: guint d;
switch (screen_desktop_layout.start_corner) {
case OB_CORNER_TOPLEFT: if (!c || !client_normal(c)) return;
return r % screen_desktop_layout.rows *
screen_desktop_layout.columns + d = screen_cycle_desktop(data->sendtodir.dir, data->sendtodir.wrap,
c % screen_desktop_layout.columns; data->sendtodir.linear,
case OB_CORNER_BOTTOMLEFT: data->sendtodir.final, data->sendtodir.cancel);
return (screen_desktop_layout.rows - 1 -
r % screen_desktop_layout.rows) * g_message("sendto %d", d);
screen_desktop_layout.columns +
c % screen_desktop_layout.columns; client_set_desktop(c, d, TRUE);
case OB_CORNER_TOPRIGHT: screen_set_desktop(d);
return r % screen_desktop_layout.rows *
screen_desktop_layout.columns +
(screen_desktop_layout.columns - 1 -
c % screen_desktop_layout.columns);
case OB_CORNER_BOTTOMRIGHT:
return (screen_desktop_layout.rows - 1 -
r % screen_desktop_layout.rows) *
screen_desktop_layout.columns +
(screen_desktop_layout.columns - 1 -
c % screen_desktop_layout.columns);
}
case OB_ORIENTATION_VERT:
switch (screen_desktop_layout.start_corner) {
case OB_CORNER_TOPLEFT:
return c % screen_desktop_layout.columns *
screen_desktop_layout.rows +
r % screen_desktop_layout.rows;
case OB_CORNER_BOTTOMLEFT:
return c % screen_desktop_layout.columns *
screen_desktop_layout.rows +
(screen_desktop_layout.rows - 1 -
r % screen_desktop_layout.rows);
case OB_CORNER_TOPRIGHT:
return (screen_desktop_layout.columns - 1 -
c % screen_desktop_layout.columns) *
screen_desktop_layout.rows +
r % screen_desktop_layout.rows;
case OB_CORNER_BOTTOMRIGHT:
return (screen_desktop_layout.columns - 1 -
c % screen_desktop_layout.columns) *
screen_desktop_layout.rows +
(screen_desktop_layout.rows - 1 -
r % screen_desktop_layout.rows);
}
}
g_assert_not_reached();
return 0;
} }
#if 0
void action_desktop_right(union ActionData *data) void action_desktop_right(union ActionData *data)
{ {
guint r, c, d; guint r, c, d;
@ -939,7 +943,8 @@ void action_desktop_right(union ActionData *data)
} }
d = translate_row_col(r, c); d = translate_row_col(r, c);
if (d < screen_num_desktops) if (d < screen_num_desktops)
screen_set_desktop(d); screen_cycle_desktop(d, data->desktopdir.final,
data->desktopdir.cancel);
} }
void action_send_to_desktop_right(union ActionData *data) void action_send_to_desktop_right(union ActionData *data)
@ -963,7 +968,9 @@ void action_send_to_desktop_right(union ActionData *data)
d = translate_row_col(r, c); d = translate_row_col(r, c);
if (d < screen_num_desktops) { if (d < screen_num_desktops) {
client_set_desktop(cl, d, data->sendtodir.follow); client_set_desktop(cl, d, data->sendtodir.follow);
if (data->sendtodir.follow) screen_set_desktop(d); if (data->sendtodir.follow)
screen_cycle_desktop(d, data->desktopdir.final,
data->desktopdir.cancel);
} }
} }
@ -984,7 +991,8 @@ void action_desktop_left(union ActionData *data)
} }
d = translate_row_col(r, c); d = translate_row_col(r, c);
if (d < screen_num_desktops) if (d < screen_num_desktops)
screen_set_desktop(d); screen_cycle_desktop(d, data->desktopdir.final,
data->desktopdir.cancel);
} }
void action_send_to_desktop_left(union ActionData *data) void action_send_to_desktop_left(union ActionData *data)
@ -1008,7 +1016,9 @@ void action_send_to_desktop_left(union ActionData *data)
d = translate_row_col(r, c); d = translate_row_col(r, c);
if (d < screen_num_desktops) { if (d < screen_num_desktops) {
client_set_desktop(cl, d, data->sendtodir.follow); client_set_desktop(cl, d, data->sendtodir.follow);
if (data->sendtodir.follow) screen_set_desktop(d); if (data->sendtodir.follow)
screen_cycle_desktop(d, data->desktopdir.final,
data->desktopdir.cancel);
} }
} }
@ -1029,7 +1039,8 @@ void action_desktop_down(union ActionData *data)
} }
d = translate_row_col(r, c); d = translate_row_col(r, c);
if (d < screen_num_desktops) if (d < screen_num_desktops)
screen_set_desktop(d); screen_cycle_desktop(d, data->desktopdir.final,
data->desktopdir.cancel);
} }
void action_send_to_desktop_down(union ActionData *data) void action_send_to_desktop_down(union ActionData *data)
@ -1051,7 +1062,9 @@ void action_send_to_desktop_down(union ActionData *data)
d = translate_row_col(r, c); d = translate_row_col(r, c);
if (d < screen_num_desktops) { if (d < screen_num_desktops) {
client_set_desktop(data->sendtodir.c, d, data->sendtodir.follow); client_set_desktop(data->sendtodir.c, d, data->sendtodir.follow);
if (data->sendtodir.follow) screen_set_desktop(d); if (data->sendtodir.follow)
screen_cycle_desktop(d, data->desktopdir.final,
data->desktopdir.cancel);
} }
} }
} }
@ -1073,7 +1086,8 @@ void action_desktop_up(union ActionData *data)
} }
d = translate_row_col(r, c); d = translate_row_col(r, c);
if (d < screen_num_desktops) if (d < screen_num_desktops)
screen_set_desktop(d); screen_cycle_desktop(d, data->desktopdir.final,
data->desktopdir.cancel);
} }
void action_send_to_desktop_up(union ActionData *data) void action_send_to_desktop_up(union ActionData *data)
@ -1095,10 +1109,13 @@ void action_send_to_desktop_up(union ActionData *data)
d = translate_row_col(r, c); d = translate_row_col(r, c);
if (d < screen_num_desktops) { if (d < screen_num_desktops) {
client_set_desktop(data->sendtodir.c, d, data->sendtodir.follow); client_set_desktop(data->sendtodir.c, d, data->sendtodir.follow);
if (data->sendtodir.follow) screen_set_desktop(d); if (data->sendtodir.follow)
screen_cycle_desktop(d, data->desktopdir.final,
data->desktopdir.cancel);
} }
} }
} }
#endif
void action_toggle_decorations(union ActionData *data) void action_toggle_decorations(union ActionData *data)
{ {

View file

@ -4,6 +4,8 @@
#include "misc.h" #include "misc.h"
#include "parser/parse.h" #include "parser/parse.h"
typedef struct _ObAction ObAction;
/* These have to all have a Client* at the top even if they don't use it, so /* 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* that I can set it blindly later on. So every function will have a Client*
available (possibly NULL though) if it wants it. available (possibly NULL though) if it wants it.
@ -40,8 +42,11 @@ struct SendToDesktop {
struct SendToDesktopDirection { struct SendToDesktopDirection {
struct _ObClient *c; struct _ObClient *c;
ObDirection dir;
gboolean wrap; gboolean wrap;
gboolean follow; gboolean linear;
gboolean final;
gboolean cancel;
}; };
struct Desktop { struct Desktop {
@ -56,7 +61,11 @@ struct Layer {
struct DesktopDirection { struct DesktopDirection {
struct _ObClient *c; struct _ObClient *c;
ObDirection dir;
gboolean wrap; gboolean wrap;
gboolean linear;
gboolean final;
gboolean cancel;
}; };
struct MoveResize { struct MoveResize {
@ -98,15 +107,15 @@ union ActionData {
struct Layer layer; struct Layer layer;
}; };
typedef struct { struct _ObAction {
/* The func member acts like an enum to tell which one of the structs in /* The func member acts like an enum to tell which one of the structs in
the data union are valid. the data union are valid.
*/ */
void (*func)(union ActionData *data); void (*func)(union ActionData *data);
union ActionData data; union ActionData data;
} Action; };
Action *action_new(void (*func)(union ActionData *data)); ObAction *action_new(void (*func)(union ActionData *data));
/* Creates a new Action from the name of the action /* Creates a new Action from the name of the action
A few action types need data set after making this call still. Check if A few action types need data set after making this call still. Check if
@ -120,9 +129,9 @@ Action *action_new(void (*func)(union ActionData *data));
action_resize_relative_vert - the delta action_resize_relative_vert - the delta
*/ */
Action *action_from_string(char *name); ObAction *action_from_string(char *name);
Action *action_parse(xmlDocPtr doc, xmlNodePtr node); ObAction *action_parse(xmlDocPtr doc, xmlNodePtr node);
void action_free(Action *a); void action_free(ObAction *a);
/* Execute */ /* Execute */
void action_execute(union ActionData *data); void action_execute(union ActionData *data);
@ -181,23 +190,11 @@ void action_toggle_maximize_vert(union ActionData *data);
/* SendToDesktop */ /* SendToDesktop */
void action_send_to_desktop(union ActionData *data); void action_send_to_desktop(union ActionData *data);
/* SendToDesktopDirection */ /* SendToDesktopDirection */
void action_send_to_desktop_right(union ActionData *data); void action_send_to_desktop_dir(union ActionData *data);
/* SendToDesktopDirection */
void action_send_to_desktop_left(union ActionData *data);
/* SendToDesktopDirection */
void action_send_to_desktop_up(union ActionData *data);
/* SendToDesktopDirection */
void action_send_to_desktop_down(union ActionData *data);
/* Desktop */ /* Desktop */
void action_desktop(union ActionData *data); void action_desktop(union ActionData *data);
/* DesktopDirection */ /* DesktopDirection */
void action_desktop_right(union ActionData *data); void action_desktop_dir(union ActionData *data);
/* DesktopDirection */
void action_desktop_left(union ActionData *data);
/* DesktopDirection */
void action_desktop_up(union ActionData *data);
/* DesktopDirection */
void action_desktop_down(union ActionData *data);
/* ClientAction */ /* ClientAction */
void action_toggle_decorations(union ActionData *data); void action_toggle_decorations(union ActionData *data);
/* MoveResize */ /* MoveResize */

View file

@ -18,6 +18,8 @@
#include "group.h" #include "group.h"
#include "config.h" #include "config.h"
#include "menu.h" #include "menu.h"
#include "keyboard.h"
#include "mouse.h"
#include "render/render.h" #include "render/render.h"
#include <glib.h> #include <glib.h>
@ -327,6 +329,9 @@ void client_manage(Window window)
/* update the list hints */ /* update the list hints */
client_set_list(); client_set_list();
keyboard_grab_for_client(self, TRUE);
mouse_grab_for_client(self, TRUE);
dispatch_client(Event_Client_Mapped, self, 0, 0); dispatch_client(Event_Client_Mapped, self, 0, 0);
ob_debug("Managed window 0x%lx (%s)\n", window, self->class); ob_debug("Managed window 0x%lx (%s)\n", window, self->class);
@ -355,6 +360,9 @@ void client_unmanage(ObClient *self)
dispatch_client(Event_Client_Destroy, self, 0, 0); dispatch_client(Event_Client_Destroy, self, 0, 0);
g_assert(self != NULL); g_assert(self != NULL);
keyboard_grab_for_client(self, FALSE);
mouse_grab_for_client(self, FALSE);
/* remove the window from our save set */ /* remove the window from our save set */
XChangeSaveSet(ob_display, self->window, SetModeDelete); XChangeSaveSet(ob_display, self->window, SetModeDelete);
@ -1097,7 +1105,7 @@ void client_setup_decor_and_functions(ObClient *self)
/* finally, the user can have requested no decorations, which overrides /* finally, the user can have requested no decorations, which overrides
everything */ everything */
if (!self->decorate) if (!self->decorate)
self->decorations = 0; self->decorations = OB_FRAME_DECOR_BORDER;
/* if we don't have a titlebar, then we cannot shade! */ /* if we don't have a titlebar, then we cannot shade! */
if (!(self->decorations & OB_FRAME_DECOR_TITLEBAR)) if (!(self->decorations & OB_FRAME_DECOR_TITLEBAR))
@ -1705,7 +1713,7 @@ void client_configure_full(ObClient *self, ObCorner anchor,
gboolean force_reply) gboolean force_reply)
{ {
gboolean moved = FALSE, resized = FALSE; gboolean moved = FALSE, resized = FALSE;
gint fdecor = self->frame->decorations; guint fdecor = self->frame->decorations;
/* make the frame recalculate its dimentions n shit without changing /* make the frame recalculate its dimentions n shit without changing
anything visible for real, this way the constraints below can work with anything visible for real, this way the constraints below can work with

View file

@ -1,4 +1,7 @@
#include "config.h" #include "config.h"
#include "keyboard.h"
#include "mouse.h"
#include "prop.h"
#include "parser/parse.h" #include "parser/parse.h"
gboolean config_focus_new; gboolean config_focus_new;
@ -25,6 +28,151 @@ ObOrientation config_dock_orient;
gboolean config_dock_hide; gboolean config_dock_hide;
guint config_dock_hide_timeout; guint config_dock_hide_timeout;
gint config_mouse_threshold;
gint config_mouse_dclicktime;
/*
<keybind key="C-x">
<action name="ChangeDesktop">
<desktop>3</desktop>
</action>
</keybind>
*/
static void parse_key(xmlDocPtr doc, xmlNodePtr node, GList *keylist)
{
char *key;
ObAction *action;
xmlNodePtr n, nact;
GList *it;
n = parse_find_node("keybind", node);
while (n) {
if (parse_attr_string("key", n, &key)) {
keylist = g_list_append(keylist, key);
parse_key(doc, n->xmlChildrenNode, keylist);
it = g_list_last(keylist);
g_free(it->data);
keylist = g_list_delete_link(keylist, it);
}
n = parse_find_node("keybind", n->next);
}
if (keylist) {
nact = parse_find_node("action", node);
while (nact) {
if ((action = action_parse(doc, nact))) {
/* validate that its okay for a key binding */
if (action->func == action_moveresize &&
action->data.moveresize.corner !=
prop_atoms.net_wm_moveresize_move_keyboard &&
action->data.moveresize.corner !=
prop_atoms.net_wm_moveresize_size_keyboard) {
action_free(action);
action = NULL;
}
if (action)
keyboard_bind(keylist, action);
}
nact = parse_find_node("action", nact->next);
}
}
}
static void parse_keyboard(xmlDocPtr doc, xmlNodePtr node, void *d)
{
parse_key(doc, node->xmlChildrenNode, NULL);
}
static int threshold;
static int dclicktime;
/*
<context name="Titlebar">
<mousebind button="Left" action="Press">
<action name="Raise"></action>
</mousebind>
</context>
*/
static void parse_mouse(xmlDocPtr doc, xmlNodePtr node, void *d)
{
xmlNodePtr n, nbut, nact;
char *buttonstr;
char *contextstr;
ObMouseAction mact;
ObAction *action;
node = node->xmlChildrenNode;
if ((n = parse_find_node("dragThreshold", node)))
threshold = parse_int(doc, n);
if ((n = parse_find_node("doubleClickTime", node)))
dclicktime = parse_int(doc, n);
n = parse_find_node("context", node);
while (n) {
if (!parse_attr_string("name", n, &contextstr))
goto next_n;
nbut = parse_find_node("mousebind", n->xmlChildrenNode);
while (nbut) {
if (!parse_attr_string("button", nbut, &buttonstr))
goto next_nbut;
if (parse_attr_contains("press", nbut, "action"))
mact = MouseAction_Press;
else if (parse_attr_contains("release", nbut, "action"))
mact = MouseAction_Release;
else if (parse_attr_contains("click", nbut, "action"))
mact = MouseAction_Click;
else if (parse_attr_contains("doubleclick", nbut,"action"))
mact = MouseAction_DClick;
else if (parse_attr_contains("drag", nbut, "action"))
mact = MouseAction_Motion;
else
goto next_nbut;
nact = parse_find_node("action", nbut->xmlChildrenNode);
while (nact) {
if ((action = action_parse(doc, nact))) {
/* validate that its okay for a mouse binding*/
if (mact == MouseAction_Motion) {
if (action->func != action_moveresize ||
action->data.moveresize.corner ==
prop_atoms.net_wm_moveresize_move_keyboard ||
action->data.moveresize.corner ==
prop_atoms.net_wm_moveresize_size_keyboard) {
action_free(action);
action = NULL;
}
} else {
if (action->func == action_moveresize &&
action->data.moveresize.corner !=
prop_atoms.net_wm_moveresize_move_keyboard &&
action->data.moveresize.corner !=
prop_atoms.net_wm_moveresize_size_keyboard) {
action_free(action);
action = NULL;
}
}
if (action)
mouse_bind(buttonstr, contextstr, mact, action);
}
nact = parse_find_node("action", nact->next);
}
g_free(buttonstr);
next_nbut:
nbut = parse_find_node("mousebind", nbut->next);
}
g_free(contextstr);
next_n:
n = parse_find_node("context", n->next);
}
}
static void parse_focus(xmlDocPtr doc, xmlNodePtr node, void *d) static void parse_focus(xmlDocPtr doc, xmlNodePtr node, void *d)
{ {
xmlNodePtr n; xmlNodePtr n;
@ -190,6 +338,13 @@ void config_startup()
config_dock_hide_timeout = 3000; config_dock_hide_timeout = 3000;
parse_register("dock", parse_dock, NULL); parse_register("dock", parse_dock, NULL);
parse_register("keyboard", parse_keyboard, NULL);
config_mouse_threshold = 3;
config_mouse_dclicktime = 200;
parse_register("mouse", parse_mouse, NULL);
} }
void config_shutdown() void config_shutdown()

View file

@ -52,6 +52,11 @@ extern int config_desktops_num;
/*! Names for the desktops */ /*! Names for the desktops */
extern GSList *config_desktops_names; extern GSList *config_desktops_names;
/*! Number of pixels a drag must go before being considered a drag */
extern gint config_mouse_threshold;
/*! Number of milliseconds within which 2 clicks must occur to be a
double-click */
extern gint config_mouse_dclicktime;
void config_startup(); void config_startup();
void config_shutdown(); void config_shutdown();

View file

@ -8,6 +8,8 @@
#include "screen.h" #include "screen.h"
#include "frame.h" #include "frame.h"
#include "menu.h" #include "menu.h"
#include "keyboard.h"
#include "mouse.h"
#include "framerender.h" #include "framerender.h"
#include "focus.h" #include "focus.h"
#include "moveresize.h" #include "moveresize.h"
@ -541,13 +543,23 @@ static void event_process(XEvent *e)
} }
/* user input (action-bound) events */ /* user input (action-bound) events */
/* if (e->type == ButtonPress || e->type == ButtonRelease ||
e->type == MotionNotify || e->type == KeyPress ||
e->type == KeyRelease)
{
ObFrameContext context;
context = frame_context(client, e->xany.window);
if (!keyboard_process_interactive_grab(e, &client, &context)) {
if (e->type == ButtonPress || e->type == ButtonRelease || if (e->type == ButtonPress || e->type == ButtonRelease ||
e->type == MotionNotify) e->type == MotionNotify)
mouse_event(e, client); mouse_event(client, context, e);
else if (e->type == KeyPress || e->type == KeyRelease) else if (e->type == KeyPress)
; keyboard_event(client, e);
*/ }
}
/* dispatch the event to registered handlers */ /* dispatch the event to registered handlers */
dispatch_x(e, client); dispatch_x(e, client);

View file

@ -281,8 +281,6 @@ ObClient *focus_cycle(gboolean forward, gboolean linear, gboolean done,
client_activate(focus_cycle_target); client_activate(focus_cycle_target);
goto done_cycle; goto done_cycle;
} }
if (!first)
grab_pointer(TRUE, None);
if (!first) first = focus_client; if (!first) first = focus_client;
if (!focus_cycle_target) focus_cycle_target = focus_client; if (!focus_cycle_target) focus_cycle_target = focus_client;
@ -331,7 +329,6 @@ done_cycle:
order = NULL; order = NULL;
popup_cycle(ft, FALSE); popup_cycle(ft, FALSE);
grab_pointer(FALSE, None);
return NULL; return NULL;
} }

265
openbox/keyboard.c Normal file
View file

@ -0,0 +1,265 @@
#include "focus.h"
#include "screen.h"
#include "frame.h"
#include "openbox.h"
#include "event.h"
#include "grab.h"
#include "client.h"
#include "action.h"
#include "prop.h"
#include "timer.h"
#include "keytree.h"
#include "keyboard.h"
#include "translate.h"
#include <glib.h>
KeyBindingTree *keyboard_firstnode;
static KeyBindingTree *curpos;
static ObTimer *chain_timer;
static gboolean interactive_grab;
static guint grabbed_state;
static ObClient *grabbed_client;
static ObAction *grabbed_action;
static ObFrameContext grabbed_context;
static void grab_for_window(Window win, gboolean grab)
{
KeyBindingTree *p;
ungrab_all_keys(win);
if (grab) {
p = curpos ? curpos->first_child : keyboard_firstnode;
while (p) {
grab_key(p->key, p->state, win, GrabModeAsync);
p = p->next_sibling;
}
}
}
void keyboard_grab_for_client(ObClient *c, gboolean grab)
{
grab_for_window(c->window, grab);
}
static void grab_keys(gboolean grab)
{
GList *it;
grab_for_window(screen_support_win, grab);
for (it = client_list; it; it = g_list_next(it))
grab_for_window(((ObClient*)it->data)->frame->window, grab);
}
void keyboard_reset_chains()
{
if (chain_timer) {
timer_stop(chain_timer);
chain_timer = NULL;
}
if (curpos) {
curpos = NULL;
grab_keys(TRUE);
}
}
static void chain_timeout(ObTimer *t, void *data)
{
keyboard_reset_chains();
}
gboolean keyboard_bind(GList *keylist, ObAction *action)
{
KeyBindingTree *tree, *t;
gboolean conflict;
g_assert(keylist != NULL);
g_assert(action != NULL);
if (!(tree = tree_build(keylist)))
return FALSE;
if ((t = tree_find(tree, &conflict)) != NULL) {
/* already bound to something, use the existing tree */
tree_destroy(tree);
tree = NULL;
} else
t = tree;
while (t->first_child) t = t->first_child;
if (conflict) {
g_warning("conflict with binding");
tree_destroy(tree);
return FALSE;
}
/* set the action */
t->actions = g_slist_append(t->actions, action);
/* assimilate this built tree into the main tree. assimilation
destroys/uses the tree */
if (tree) tree_assimilate(tree);
return TRUE;
}
void keyboard_interactive_grab(guint state, ObClient *client,
ObFrameContext context, ObAction *action)
{
if (!interactive_grab && grab_keyboard(TRUE)) {
interactive_grab = TRUE;
grabbed_state = state;
grabbed_client = client;
grabbed_action = action;
grabbed_context = context;
grab_pointer(TRUE, None);
}
}
gboolean keyboard_process_interactive_grab(const XEvent *e,
ObClient **client,
ObFrameContext *context)
{
gboolean handled = FALSE;
gboolean done = FALSE;
if (interactive_grab) {
*client = grabbed_client;
*context = grabbed_context;
}
if ((e->type == KeyRelease &&
!(grabbed_state & e->xkey.state)))
done = TRUE;
else if (e->type == KeyPress) {
if (e->xkey.keycode == ob_keycode(OB_KEY_RETURN))
done = TRUE;
else if (e->xkey.keycode == ob_keycode(OB_KEY_ESCAPE)) {
if (grabbed_action->func == action_cycle_windows) {
grabbed_action->data.cycle.cancel = TRUE;
}
if (grabbed_action->func == action_desktop_dir) {
grabbed_action->data.desktopdir.cancel = TRUE;
}
if (grabbed_action->func == action_send_to_desktop_dir)
{
grabbed_action->data.sendtodir.cancel = TRUE;
}
done = TRUE;
}
}
if (done) {
if (grabbed_action->func == action_cycle_windows) {
grabbed_action->data.cycle.final = TRUE;
}
if (grabbed_action->func == action_desktop_dir) {
grabbed_action->data.desktopdir.final = TRUE;
}
if (grabbed_action->func == action_send_to_desktop_dir) {
grabbed_action->data.sendtodir.final = TRUE;
}
grabbed_action->func(&grabbed_action->data);
interactive_grab = FALSE;
grab_keyboard(FALSE);
grab_pointer(FALSE, None);
keyboard_reset_chains();
handled = TRUE;
}
return handled;
}
void keyboard_event(ObClient *client, const XEvent *e)
{
KeyBindingTree *p;
g_assert(e->type == KeyPress);
if (curpos == NULL)
p = keyboard_firstnode;
else
p = curpos->first_child;
while (p) {
if (p->key == e->xkey.keycode &&
p->state == e->xkey.state) {
if (p->first_child != NULL) { /* part of a chain */
if (chain_timer) timer_stop(chain_timer);
/* 5 second timeout for chains */
chain_timer = timer_start(5000*1000, chain_timeout,
NULL);
curpos = p;
grab_keys(TRUE);
} else {
GSList *it;
for (it = p->actions; it; it = it->next) {
ObAction *act = it->data;
if (act->func != NULL) {
act->data.any.c = client;
if (act->func == action_cycle_windows)
{
act->data.cycle.final = FALSE;
act->data.cycle.cancel = FALSE;
}
if (act->func == action_desktop_dir)
{
act->data.desktopdir.final = FALSE;
act->data.desktopdir.cancel = FALSE;
}
if (act->func == action_send_to_desktop_dir)
{
act->data.sendtodir.final = FALSE;
act->data.sendtodir.cancel = FALSE;
}
if (act->func == action_moveresize)
{
screen_pointer_pos(&act->data.moveresize.x,
&act->data.moveresize.y);
}
if ((act->func == action_cycle_windows ||
act->func == action_desktop_dir ||
act->func == action_send_to_desktop_dir))
{
keyboard_interactive_grab(e->xkey.state, client,
0, act);
}
if (act->func == action_showmenu)
{
act->data.showmenu.x =
e->xkey.x_root;
act->data.showmenu.y =
e->xkey.y_root;
}
act->data.any.c = client;
act->func(&act->data);
}
}
keyboard_reset_chains();
}
break;
}
p = p->next_sibling;
}
}
void keyboard_startup()
{
grab_keys(TRUE);
}
void keyboard_shutdown()
{
tree_destroy(keyboard_firstnode);
keyboard_firstnode = NULL;
grab_keys(FALSE);
}

32
openbox/keyboard.h Normal file
View file

@ -0,0 +1,32 @@
#ifndef ob__keybaord_h
#define ob__keybaord_h
#include "keytree.h"
#include "frame.h"
#include <glib.h>
#include <X11/Xlib.h>
struct _ObClient;
struct _ObAction;
extern KeyBindingTree *keyboard_firstnode;
void keyboard_startup();
void keyboard_shutdown();
gboolean keyboard_bind(GList *keylist, ObAction *action);
void keyboard_event(struct _ObClient *client, const XEvent *e);
void keyboard_reset_chains();
void keyboard_interactive_grab(guint state, struct _ObClient *client,
ObFrameContext context,
struct _ObAction *action);
gboolean keyboard_process_interactive_grab(const XEvent *e,
struct _ObClient **client,
ObFrameContext *context);
void keyboard_grab_for_client(struct _ObClient *c, gboolean grab);
#endif

112
openbox/keytree.c Normal file
View file

@ -0,0 +1,112 @@
#include "keyboard.h"
#include "translate.h"
#include <glib.h>
void tree_destroy(KeyBindingTree *tree)
{
KeyBindingTree *c;
while (tree) {
tree_destroy(tree->next_sibling);
c = tree->first_child;
if (c == NULL) {
GList *it;
GSList *sit;
for (it = tree->keylist; it != NULL; it = it->next)
g_free(it->data);
g_list_free(tree->keylist);
for (sit = tree->actions; sit != NULL; sit = sit->next)
action_free(sit->data);
g_slist_free(tree->actions);
}
g_free(tree);
tree = c;
}
}
KeyBindingTree *tree_build(GList *keylist)
{
GList *it;
KeyBindingTree *ret = NULL, *p;
if (g_list_length(keylist) <= 0)
return NULL; /* nothing in the list.. */
for (it = g_list_last(keylist); it != NULL; it = it->prev) {
p = ret;
ret = g_new0(KeyBindingTree, 1);
if (p == NULL) {
GList *it;
/* this is the first built node, the bottom node of the tree */
ret->keylist = g_list_copy(keylist); /* shallow copy */
for (it = ret->keylist; it != NULL; it = it->next) /* deep copy */
it->data = g_strdup(it->data);
}
ret->first_child = p;
if (!translate_key(it->data, &ret->state, &ret->key)) {
tree_destroy(ret);
return NULL;
}
}
return ret;
}
void tree_assimilate(KeyBindingTree *node)
{
KeyBindingTree *a, *b, *tmp, *last;
if (keyboard_firstnode == NULL) {
/* there are no nodes at this level yet */
keyboard_firstnode = node;
} else {
a = keyboard_firstnode;
last = a;
b = node;
while (a) {
last = a;
if (!(a->state == b->state && a->key == b->key)) {
a = a->next_sibling;
} else {
tmp = b;
b = b->first_child;
g_free(tmp);
a = a->first_child;
}
}
if (!(last->state == b->state && last->key == b->key))
last->next_sibling = b;
else {
last->first_child = b->first_child;
g_free(b);
}
}
}
KeyBindingTree *tree_find(KeyBindingTree *search, gboolean *conflict)
{
KeyBindingTree *a, *b;
*conflict = FALSE;
a = keyboard_firstnode;
b = search;
while (a && b) {
if (!(a->state == b->state && a->key == b->key)) {
a = a->next_sibling;
} else {
if ((a->first_child == NULL) == (b->first_child == NULL)) {
if (a->first_child == NULL) {
/* found it! (return the actual node, not the search's) */
return a;
}
} else {
*conflict = TRUE;
return NULL; /* the chain status' don't match (conflict!) */
}
b = b->first_child;
a = a->first_child;
}
}
return NULL; /* it just isn't in here */
}

25
openbox/keytree.h Normal file
View file

@ -0,0 +1,25 @@
#ifndef __plugin_keyboard_tree_h
#define __plugin_keyboard_tree_h
#include "action.h"
#include <glib.h>
typedef struct KeyBindingTree {
guint state;
guint key;
GList *keylist;
GSList *actions; /* list of Action pointers */
/* the next binding in the tree at the same level */
struct KeyBindingTree *next_sibling;
/* the first child of this binding (next binding in a chained sequence).*/
struct KeyBindingTree *first_child;
} KeyBindingTree;
void tree_destroy(KeyBindingTree *tree);
KeyBindingTree *tree_build(GList *keylist);
void tree_assimilate(KeyBindingTree *node);
KeyBindingTree *tree_find(KeyBindingTree *search, gboolean *conflict);
#endif

View file

@ -27,7 +27,7 @@ static void parse_menu(xmlDocPtr doc, xmlNodePtr node, void *data)
void parse_menu_full(xmlDocPtr doc, xmlNodePtr node, void *data, void parse_menu_full(xmlDocPtr doc, xmlNodePtr node, void *data,
gboolean newmenu) gboolean newmenu)
{ {
Action *act; ObAction *act;
xmlNodePtr nact; xmlNodePtr nact;
gchar *id = NULL, *title = NULL, *label = NULL, *plugin; gchar *id = NULL, *title = NULL, *label = NULL, *plugin;
@ -233,7 +233,7 @@ void menu_free(char *name)
g_hash_table_remove(menu_hash, name); g_hash_table_remove(menu_hash, name);
} }
ObMenuEntry *menu_entry_new_full(char *label, Action *action, ObMenuEntry *menu_entry_new_full(char *label, ObAction *action,
ObMenuEntryRenderType render_type, ObMenuEntryRenderType render_type,
gpointer submenu) gpointer submenu)
{ {

View file

@ -103,7 +103,7 @@ struct _ObMenuEntry
char *label; char *label;
ObMenu *parent; ObMenu *parent;
Action *action; ObAction *action;
ObMenuEntryRenderType render_type; ObMenuEntryRenderType render_type;
gboolean hilite; gboolean hilite;
@ -155,7 +155,7 @@ void menu_hide(ObMenu *self);
void menu_clear(ObMenu *self); void menu_clear(ObMenu *self);
ObMenuEntry *menu_entry_new_full(char *label, Action *action, ObMenuEntry *menu_entry_new_full(char *label, ObAction *action,
ObMenuEntryRenderType render_type, ObMenuEntryRenderType render_type,
gpointer submenu); gpointer submenu);

View file

@ -1,112 +1,26 @@
#include "kernel/openbox.h" #include "openbox.h"
#include "kernel/dispatch.h" #include "config.h"
#include "kernel/action.h" #include "action.h"
#include "kernel/event.h" #include "event.h"
#include "kernel/client.h" #include "client.h"
#include "kernel/prop.h" #include "prop.h"
#include "kernel/grab.h" #include "grab.h"
#include "kernel/frame.h" #include "frame.h"
#include "parser/parse.h"
#include "translate.h" #include "translate.h"
#include "mouse.h" #include "mouse.h"
#include "keyboard.h"
#include <glib.h> #include <glib.h>
static int threshold; typedef struct {
static int dclicktime; guint state;
/* guint button;
GSList *actions[NUM_MOUSEACTION]; /* lists of Action pointers */
<context name="Titlebar"> } ObMouseBinding;
<mousebind button="Left" action="Press">
<action name="Raise"></action>
</mousebind>
</context>
*/
static void parse_xml(xmlDocPtr doc, xmlNodePtr node, void *d)
{
xmlNodePtr n, nbut, nact;
char *buttonstr;
char *contextstr;
MouseAction mact;
Action *action;
node = node->xmlChildrenNode;
if ((n = parse_find_node("dragThreshold", node)))
threshold = parse_int(doc, n);
if ((n = parse_find_node("doubleClickTime", node)))
dclicktime = parse_int(doc, n);
n = parse_find_node("context", node);
while (n) {
if (!parse_attr_string("name", n, &contextstr))
goto next_n;
nbut = parse_find_node("mousebind", n->xmlChildrenNode);
while (nbut) {
if (!parse_attr_string("button", nbut, &buttonstr))
goto next_nbut;
if (parse_attr_contains("press", nbut, "action"))
mact = MouseAction_Press;
else if (parse_attr_contains("release", nbut, "action"))
mact = MouseAction_Release;
else if (parse_attr_contains("click", nbut, "action"))
mact = MouseAction_Click;
else if (parse_attr_contains("doubleclick", nbut,"action"))
mact = MouseAction_DClick;
else if (parse_attr_contains("drag", nbut, "action"))
mact = MouseAction_Motion;
else
goto next_nbut;
nact = parse_find_node("action", nbut->xmlChildrenNode);
while (nact) {
if ((action = action_parse(doc, nact))) {
/* validate that its okay for a mouse binding*/
if (mact == MouseAction_Motion) {
if (action->func != action_moveresize ||
action->data.moveresize.corner ==
prop_atoms.net_wm_moveresize_move_keyboard ||
action->data.moveresize.corner ==
prop_atoms.net_wm_moveresize_size_keyboard) {
action_free(action);
action = NULL;
}
} else {
if (action->func == action_moveresize &&
action->data.moveresize.corner !=
prop_atoms.net_wm_moveresize_move_keyboard &&
action->data.moveresize.corner !=
prop_atoms.net_wm_moveresize_size_keyboard) {
action_free(action);
action = NULL;
}
}
if (action)
mbind(buttonstr, contextstr, mact, action);
}
nact = parse_find_node("action", nact->next);
}
g_free(buttonstr);
next_nbut:
nbut = parse_find_node("mousebind", nbut->next);
}
g_free(contextstr);
next_n:
n = parse_find_node("context", n->next);
}
}
void plugin_setup_config()
{
threshold = 3;
dclicktime = 200;
parse_register("mouse", parse_xml, NULL);
}
/* Array of GSList*s of PointerBinding*s. */ /* Array of GSList*s of PointerBinding*s. */
static GSList *bound_contexts[OB_FRAME_NUM_CONTEXTS]; static GSList *bound_contexts[OB_FRAME_NUM_CONTEXTS];
static void grab_for_client(ObClient *client, gboolean grab) void mouse_grab_for_client(ObClient *client, gboolean grab)
{ {
int i; int i;
GSList *it; GSList *it;
@ -114,7 +28,7 @@ static void grab_for_client(ObClient *client, gboolean grab)
for (i = 0; i < OB_FRAME_NUM_CONTEXTS; ++i) for (i = 0; i < OB_FRAME_NUM_CONTEXTS; ++i)
for (it = bound_contexts[i]; it != NULL; it = it->next) { for (it = bound_contexts[i]; it != NULL; it = it->next) {
/* grab/ungrab the button */ /* grab/ungrab the button */
MouseBinding *b = it->data; ObMouseBinding *b = it->data;
Window win; Window win;
int mode; int mode;
unsigned int mask; unsigned int mask;
@ -143,7 +57,7 @@ static void grab_all_clients(gboolean grab)
GList *it; GList *it;
for (it = client_list; it != NULL; it = it->next) for (it = client_list; it != NULL; it = it->next)
grab_for_client(it->data, grab); mouse_grab_for_client(it->data, grab);
} }
static void clearall() static void clearall()
@ -155,7 +69,7 @@ static void clearall()
for (it = bound_contexts[i]; it != NULL; it = it->next) { for (it = bound_contexts[i]; it != NULL; it = it->next) {
int j; int j;
MouseBinding *b = it->data; ObMouseBinding *b = it->data;
for (j = 0; j < NUM_MOUSEACTION; ++j) { for (j = 0; j < NUM_MOUSEACTION; ++j) {
GSList *it; GSList *it;
for (it = b->actions[j]; it; it = it->next) { for (it = b->actions[j]; it; it = it->next) {
@ -169,12 +83,14 @@ static void clearall()
} }
} }
static void fire_button(MouseAction a, ObFrameContext context, static void fire_button(ObMouseAction a, ObFrameContext context,
ObClient *c, guint state, ObClient *c, guint state,
guint button, int x, int y) guint button, int x, int y)
{ {
GSList *it; GSList *it;
MouseBinding *b; ObMouseBinding *b;
g_message("%d %d %d", context, state, button);
for (it = bound_contexts[context]; it != NULL; it = it->next) { for (it = bound_contexts[context]; it != NULL; it = it->next) {
b = it->data; b = it->data;
@ -185,7 +101,7 @@ static void fire_button(MouseAction a, ObFrameContext context,
if (it == NULL) return; if (it == NULL) return;
for (it = b->actions[a]; it; it = it->next) { for (it = b->actions[a]; it; it = it->next) {
Action *act = it->data; ObAction *act = it->data;
if (act->func != NULL) { if (act->func != NULL) {
act->data.any.c = c; act->data.any.c = c;
@ -196,17 +112,35 @@ static void fire_button(MouseAction a, ObFrameContext context,
act->data.showmenu.y = y; act->data.showmenu.y = y;
} }
if (act->func == action_desktop_dir)
{
act->data.desktopdir.final = FALSE;
act->data.desktopdir.cancel = FALSE;
}
if (act->func == action_send_to_desktop_dir)
{
act->data.sendtodir.final = FALSE;
act->data.sendtodir.cancel = FALSE;
}
if ((act->func == action_desktop_dir ||
act->func == action_send_to_desktop_dir)) {
keyboard_interactive_grab(state, c, context, act);
}
g_message("acting");
act->func(&act->data); act->func(&act->data);
} }
} }
} }
static void fire_motion(MouseAction a, ObFrameContext context, ObClient *c, static void fire_motion(ObMouseAction a, ObFrameContext context, ObClient *c,
guint state, guint button, int x_root, int y_root, guint state, guint button, int x_root, int y_root,
guint32 corner) guint32 corner)
{ {
GSList *it; GSList *it;
MouseBinding *b; ObMouseBinding *b;
for (it = bound_contexts[context]; it != NULL; it = it->next) { for (it = bound_contexts[context]; it != NULL; it = it->next) {
b = it->data; b = it->data;
@ -217,7 +151,7 @@ static void fire_motion(MouseAction a, ObFrameContext context, ObClient *c,
if (it == NULL) return; if (it == NULL) return;
for (it = b->actions[a]; it; it = it->next) { for (it = b->actions[a]; it; it = it->next) {
Action *act = it->data; ObAction *act = it->data;
if (act->func != NULL) { if (act->func != NULL) {
act->data.any.c = c; act->data.any.c = c;
@ -255,38 +189,27 @@ static guint32 pick_corner(int x, int y, int cx, int cy, int cw, int ch)
} }
} }
static void event(ObEvent *e, void *foo) void mouse_event(ObClient *client, ObFrameContext context, XEvent *e)
{ {
static Time ltime; static Time ltime;
static guint button = 0, state = 0, lbutton = 0; static guint button = 0, state = 0, lbutton = 0;
static Window lwindow = None; static Window lwindow = None;
static int px, py; static int px, py;
gboolean click = FALSE; gboolean click = FALSE;
gboolean dclick = FALSE; gboolean dclick = FALSE;
ObFrameContext context;
switch (e->type) { switch (e->type) {
case Event_Client_Mapped: case ButtonPress:
grab_for_client(e->data.c.client, TRUE); px = e->xbutton.x_root;
break; py = e->xbutton.y_root;
button = e->xbutton.button;
case Event_Client_Destroy: state = e->xbutton.state;
grab_for_client(e->data.c.client, FALSE);
break;
case Event_X_ButtonPress:
context = frame_context(e->data.x.client,
e->data.x.e->xbutton.window);
px = e->data.x.e->xbutton.x_root;
py = e->data.x.e->xbutton.y_root;
button = e->data.x.e->xbutton.button;
state = e->data.x.e->xbutton.state;
fire_button(MouseAction_Press, context, fire_button(MouseAction_Press, context,
e->data.x.client, e->data.x.e->xbutton.state, client, e->xbutton.state,
e->data.x.e->xbutton.button, e->xbutton.button,
e->data.x.e->xbutton.x_root, e->data.x.e->xbutton.y_root); e->xbutton.x_root, e->xbutton.y_root);
if (context == OB_FRAME_CONTEXT_CLIENT) { if (context == OB_FRAME_CONTEXT_CLIENT) {
/* Replay the event, so it goes to the client*/ /* Replay the event, so it goes to the client*/
@ -295,30 +218,29 @@ static void event(ObEvent *e, void *foo)
} else } else
break; break;
case Event_X_ButtonRelease: case ButtonRelease:
context = frame_context(e->data.x.client, if (e->xbutton.button == button) {
e->data.x.e->xbutton.window);
if (e->data.x.e->xbutton.button == button) {
/* clicks are only valid if its released over the window */ /* clicks are only valid if its released over the window */
int junk1, junk2; int junk1, junk2;
Window wjunk; Window wjunk;
guint ujunk, b, w, h; guint ujunk, b, w, h;
XGetGeometry(ob_display, e->data.x.e->xbutton.window, XGetGeometry(ob_display, e->xbutton.window,
&wjunk, &junk1, &junk2, &w, &h, &b, &ujunk); &wjunk, &junk1, &junk2, &w, &h, &b, &ujunk);
if (e->data.x.e->xbutton.x >= (signed)-b && if (e->xbutton.x >= (signed)-b &&
e->data.x.e->xbutton.y >= (signed)-b && e->xbutton.y >= (signed)-b &&
e->data.x.e->xbutton.x < (signed)(w+b) && e->xbutton.x < (signed)(w+b) &&
e->data.x.e->xbutton.y < (signed)(h+b)) { e->xbutton.y < (signed)(h+b)) {
click = TRUE; click = TRUE;
/* double clicks happen if there were 2 in a row! */ /* double clicks happen if there were 2 in a row! */
if (lbutton == button && if (lbutton == button &&
lwindow == e->data.x.e->xbutton.window && lwindow == e->xbutton.window &&
e->data.x.e->xbutton.time - dclicktime <= ltime) { e->xbutton.time - config_mouse_dclicktime <=
ltime) {
dclick = TRUE; dclick = TRUE;
lbutton = 0; lbutton = 0;
} else { } else {
lbutton = button; lbutton = button;
lwindow = e->data.x.e->xbutton.window; lwindow = e->xbutton.window;
} }
} else { } else {
lbutton = 0; lbutton = 0;
@ -327,35 +249,34 @@ static void event(ObEvent *e, void *foo)
button = 0; button = 0;
state = 0; state = 0;
ltime = e->data.x.e->xbutton.time; ltime = e->xbutton.time;
} }
fire_button(MouseAction_Release, context, fire_button(MouseAction_Release, context,
e->data.x.client, e->data.x.e->xbutton.state, client, e->xbutton.state,
e->data.x.e->xbutton.button, e->xbutton.button,
e->data.x.e->xbutton.x_root, e->data.x.e->xbutton.y_root); e->xbutton.x_root, e->xbutton.y_root);
if (click) if (click)
fire_button(MouseAction_Click, context, fire_button(MouseAction_Click, context,
e->data.x.client, e->data.x.e->xbutton.state, client, e->xbutton.state,
e->data.x.e->xbutton.button, e->xbutton.button,
e->data.x.e->xbutton.x_root, e->xbutton.x_root,
e->data.x.e->xbutton.y_root); e->xbutton.y_root);
if (dclick) if (dclick)
fire_button(MouseAction_DClick, context, fire_button(MouseAction_DClick, context,
e->data.x.client, e->data.x.e->xbutton.state, client, e->xbutton.state,
e->data.x.e->xbutton.button, e->xbutton.button,
e->data.x.e->xbutton.x_root, e->xbutton.x_root,
e->data.x.e->xbutton.y_root); e->xbutton.y_root);
break; break;
case Event_X_MotionNotify: case MotionNotify:
if (button) { if (button) {
if (ABS(e->data.x.e->xmotion.x_root - px) >= threshold || if (ABS(e->xmotion.x_root - px) >=
ABS(e->data.x.e->xmotion.y_root - py) >= threshold) { config_mouse_threshold ||
ABS(e->xmotion.y_root - py) >=
config_mouse_threshold) {
guint32 corner; guint32 corner;
context = frame_context(e->data.x.client,
e->data.x.e->xmotion.window);
/* You can't drag on buttons */ /* You can't drag on buttons */
if (context == OB_FRAME_CONTEXT_MAXIMIZE || if (context == OB_FRAME_CONTEXT_MAXIMIZE ||
context == OB_FRAME_CONTEXT_ALLDESKTOPS || context == OB_FRAME_CONTEXT_ALLDESKTOPS ||
@ -365,26 +286,26 @@ static void event(ObEvent *e, void *foo)
context == OB_FRAME_CONTEXT_CLOSE) context == OB_FRAME_CONTEXT_CLOSE)
break; break;
if (!e->data.x.client) if (!client)
corner = prop_atoms.net_wm_moveresize_size_bottomright; corner = prop_atoms.net_wm_moveresize_size_bottomright;
else else
corner = corner =
pick_corner(e->data.x.e->xmotion.x_root, pick_corner(e->xmotion.x_root,
e->data.x.e->xmotion.y_root, e->xmotion.y_root,
e->data.x.client->frame->area.x, client->frame->area.x,
e->data.x.client->frame->area.y, client->frame->area.y,
/* use the client size because the frame /* use the client size because the frame
can be differently sized (shaded can be differently sized (shaded
windows) and we want this based on the windows) and we want this based on the
clients size */ clients size */
e->data.x.client->area.width + client->area.width +
e->data.x.client->frame->size.left + client->frame->size.left +
e->data.x.client->frame->size.right, client->frame->size.right,
e->data.x.client->area.height + client->area.height +
e->data.x.client->frame->size.top + client->frame->size.top +
e->data.x.client->frame->size.bottom); client->frame->size.bottom);
fire_motion(MouseAction_Motion, context, fire_motion(MouseAction_Motion, context,
e->data.x.client, state, button, px, py, corner); client, state, button, px, py, corner);
button = 0; button = 0;
state = 0; state = 0;
} }
@ -396,12 +317,12 @@ static void event(ObEvent *e, void *foo)
} }
} }
gboolean mbind(char *buttonstr, char *contextstr, MouseAction mact, gboolean mouse_bind(char *buttonstr, char *contextstr, ObMouseAction mact,
Action *action) ObAction *action)
{ {
guint state, button; guint state, button;
ObFrameContext context; ObFrameContext context;
MouseBinding *b; ObMouseBinding *b;
GSList *it; GSList *it;
if (!translate_button(buttonstr, &state, &button)) { if (!translate_button(buttonstr, &state, &button)) {
@ -429,7 +350,7 @@ gboolean mbind(char *buttonstr, char *contextstr, MouseAction mact,
grab_all_clients(FALSE); grab_all_clients(FALSE);
/* add the binding */ /* add the binding */
b = g_new0(MouseBinding, 1); b = g_new0(ObMouseBinding, 1);
b->state = state; b->state = state;
b->button = button; b->button = button;
b->actions[mact] = g_slist_append(NULL, action); b->actions[mact] = g_slist_append(NULL, action);
@ -440,17 +361,12 @@ gboolean mbind(char *buttonstr, char *contextstr, MouseAction mact,
return TRUE; return TRUE;
} }
void plugin_startup() void mouse_startup()
{ {
dispatch_register(Event_Client_Mapped | Event_Client_Destroy |
Event_X_ButtonPress | Event_X_ButtonRelease |
Event_X_MotionNotify, (EventHandler)event, NULL);
} }
void plugin_shutdown() void mouse_shutdown()
{ {
dispatch_register(0, (EventHandler)event, NULL);
grab_all_clients(FALSE); grab_all_clients(FALSE);
clearall(); clearall();
} }

28
openbox/mouse.h Normal file
View file

@ -0,0 +1,28 @@
#ifndef ob__mouse_h
#define ob__mouse_h
#include "action.h"
#include "frame.h"
#include <X11/Xlib.h>
typedef enum {
MouseAction_Press,
MouseAction_Release,
MouseAction_Click,
MouseAction_DClick,
MouseAction_Motion,
NUM_MOUSEACTION
} ObMouseAction;
void mouse_startup();
void mouse_shutdown();
gboolean mouse_bind(char *buttonstr, char *contextstr, ObMouseAction mact,
ObAction *action);
void mouse_event(struct _ObClient *client, ObFrameContext context, XEvent *e);
void mouse_grab_for_client(struct _ObClient *client, gboolean grab);
#endif

View file

@ -13,6 +13,8 @@
#include "focus.h" #include "focus.h"
#include "moveresize.h" #include "moveresize.h"
#include "frame.h" #include "frame.h"
#include "keyboard.h"
#include "mouse.h"
#include "extensions.h" #include "extensions.h"
#include "grab.h" #include "grab.h"
#include "plugin.h" #include "plugin.h"
@ -243,6 +245,8 @@ int main(int argc, char **argv)
group_startup(); group_startup();
client_startup(); client_startup();
dock_startup(); dock_startup();
keyboard_startup();
mouse_startup();
/* call startup for all the plugins */ /* call startup for all the plugins */
plugin_startall(); plugin_startall();
@ -259,6 +263,8 @@ int main(int argc, char **argv)
client_unmanage_all(); client_unmanage_all();
plugin_shutdown(); /* calls all the plugins' shutdown functions */ plugin_shutdown(); /* calls all the plugins' shutdown functions */
mouse_shutdown();
keyboard_shutdown();
dock_shutdown(); dock_shutdown();
client_shutdown(); client_shutdown();
group_shutdown(); group_shutdown();

View file

@ -156,8 +156,6 @@ void plugin_loadall()
if (io == NULL) { if (io == NULL) {
/* load the default plugins */ /* load the default plugins */
plugin_open("keyboard");
plugin_open("mouse");
plugin_open("placement"); plugin_open("placement");
plugin_open("resistance"); plugin_open("resistance");

View file

@ -4,6 +4,7 @@
#include "xerror.h" #include "xerror.h"
#include "prop.h" #include "prop.h"
#include "startup.h" #include "startup.h"
#include "grab.h"
#include "timer.h" #include "timer.h"
#include "config.h" #include "config.h"
#include "screen.h" #include "screen.h"
@ -25,6 +26,7 @@
# include <sys/types.h> # include <sys/types.h>
# include <unistd.h> # include <unistd.h>
#endif #endif
#include <assert.h>
/*! The event mask to grab on the root window */ /*! The event mask to grab on the root window */
#define ROOT_EVENTMASK (StructureNotifyMask | PropertyChangeMask | \ #define ROOT_EVENTMASK (StructureNotifyMask | PropertyChangeMask | \
@ -45,7 +47,6 @@ static Rect **area; /* array of desktop holding array of xinerama areas */
static Rect *monitor_area; static Rect *monitor_area;
static Popup *desktop_cycle_popup; static Popup *desktop_cycle_popup;
static ObTimer *popup_timer = NULL;
#ifdef USE_LIBSN #ifdef USE_LIBSN
static SnMonitorContext *sn_context; static SnMonitorContext *sn_context;
@ -420,36 +421,6 @@ void screen_set_num_desktops(guint num)
screen_set_desktop(num - 1); screen_set_desktop(num - 1);
} }
static void popup_cycle_hide(ObTimer *t, void *d)
{
timer_stop(t);
popup_timer = NULL;
popup_hide(desktop_cycle_popup);
}
static void popup_cycle_show()
{
Rect *a;
a = screen_physical_area_monitor(0);
popup_position(desktop_cycle_popup, CenterGravity,
a->x + a->width / 2, a->y + a->height / 2);
/* XXX the size and the font extents need to be related on some level
*/
popup_size(desktop_cycle_popup, POPUP_WIDTH, POPUP_HEIGHT);
popup_set_text_align(desktop_cycle_popup, RR_JUSTIFY_CENTER);
popup_show(desktop_cycle_popup,
screen_desktop_names[screen_desktop], NULL);
g_message("%s", screen_desktop_names[screen_desktop]);
if (popup_timer) timer_stop(popup_timer);
popup_timer = timer_start(G_USEC_PER_SEC / 2, popup_cycle_hide, NULL);
}
void screen_set_desktop(guint num) void screen_set_desktop(guint num)
{ {
GList *it; GList *it;
@ -498,12 +469,250 @@ void screen_set_desktop(guint num)
ob_debug("/switch fallback\n"); ob_debug("/switch fallback\n");
#endif #endif
if (ob_state() == OB_STATE_RUNNING)
popup_cycle_show();
dispatch_ob(Event_Ob_Desktop, num, old); dispatch_ob(Event_Ob_Desktop, num, old);
} }
static void get_row_col(guint d, guint *r, guint *c)
{
switch (screen_desktop_layout.orientation) {
case OB_ORIENTATION_HORZ:
switch (screen_desktop_layout.start_corner) {
case OB_CORNER_TOPLEFT:
*r = d / screen_desktop_layout.columns;
*c = d % screen_desktop_layout.columns;
break;
case OB_CORNER_BOTTOMLEFT:
*r = screen_desktop_layout.rows - 1 -
d / screen_desktop_layout.columns;
*c = d % screen_desktop_layout.columns;
break;
case OB_CORNER_TOPRIGHT:
*r = d / screen_desktop_layout.columns;
*c = screen_desktop_layout.columns - 1 -
d % screen_desktop_layout.columns;
break;
case OB_CORNER_BOTTOMRIGHT:
*r = screen_desktop_layout.rows - 1 -
d / screen_desktop_layout.columns;
*c = screen_desktop_layout.columns - 1 -
d % screen_desktop_layout.columns;
break;
}
break;
case OB_ORIENTATION_VERT:
switch (screen_desktop_layout.start_corner) {
case OB_CORNER_TOPLEFT:
*r = d % screen_desktop_layout.rows;
*c = d / screen_desktop_layout.rows;
break;
case OB_CORNER_BOTTOMLEFT:
*r = screen_desktop_layout.rows - 1 -
d % screen_desktop_layout.rows;
*c = d / screen_desktop_layout.rows;
break;
case OB_CORNER_TOPRIGHT:
*r = d % screen_desktop_layout.rows;
*c = screen_desktop_layout.columns - 1 -
d / screen_desktop_layout.rows;
break;
case OB_CORNER_BOTTOMRIGHT:
*r = screen_desktop_layout.rows - 1 -
d % screen_desktop_layout.rows;
*c = screen_desktop_layout.columns - 1 -
d / screen_desktop_layout.rows;
break;
}
break;
}
}
static guint translate_row_col(guint r, guint c)
{
switch (screen_desktop_layout.orientation) {
case OB_ORIENTATION_HORZ:
switch (screen_desktop_layout.start_corner) {
case OB_CORNER_TOPLEFT:
return r % screen_desktop_layout.rows *
screen_desktop_layout.columns +
c % screen_desktop_layout.columns;
case OB_CORNER_BOTTOMLEFT:
return (screen_desktop_layout.rows - 1 -
r % screen_desktop_layout.rows) *
screen_desktop_layout.columns +
c % screen_desktop_layout.columns;
case OB_CORNER_TOPRIGHT:
return r % screen_desktop_layout.rows *
screen_desktop_layout.columns +
(screen_desktop_layout.columns - 1 -
c % screen_desktop_layout.columns);
case OB_CORNER_BOTTOMRIGHT:
return (screen_desktop_layout.rows - 1 -
r % screen_desktop_layout.rows) *
screen_desktop_layout.columns +
(screen_desktop_layout.columns - 1 -
c % screen_desktop_layout.columns);
}
case OB_ORIENTATION_VERT:
switch (screen_desktop_layout.start_corner) {
case OB_CORNER_TOPLEFT:
return c % screen_desktop_layout.columns *
screen_desktop_layout.rows +
r % screen_desktop_layout.rows;
case OB_CORNER_BOTTOMLEFT:
return c % screen_desktop_layout.columns *
screen_desktop_layout.rows +
(screen_desktop_layout.rows - 1 -
r % screen_desktop_layout.rows);
case OB_CORNER_TOPRIGHT:
return (screen_desktop_layout.columns - 1 -
c % screen_desktop_layout.columns) *
screen_desktop_layout.rows +
r % screen_desktop_layout.rows;
case OB_CORNER_BOTTOMRIGHT:
return (screen_desktop_layout.columns - 1 -
c % screen_desktop_layout.columns) *
screen_desktop_layout.rows +
(screen_desktop_layout.rows - 1 -
r % screen_desktop_layout.rows);
}
}
g_assert_not_reached();
return 0;
}
static void popup_cycle(guint d, gboolean show)
{
Rect *a;
if (!show) {
popup_hide(desktop_cycle_popup);
} else {
a = screen_physical_area_monitor(0);
popup_position(desktop_cycle_popup, CenterGravity,
a->x + a->width / 2, a->y + a->height / 2);
/* XXX the size and the font extents need to be related on some level
*/
popup_size(desktop_cycle_popup, POPUP_WIDTH, POPUP_HEIGHT);
popup_set_text_align(desktop_cycle_popup, RR_JUSTIFY_CENTER);
popup_show(desktop_cycle_popup,
screen_desktop_names[d], NULL);
}
}
guint screen_cycle_desktop(ObDirection dir, gboolean wrap, gboolean linear,
gboolean done, gboolean cancel)
{
static gboolean first = TRUE;
static gboolean lin;
static guint origd, d;
guint r, c;
if (cancel) {
d = origd;
goto done_cycle;
} else if (done) {
screen_set_desktop(d);
goto done_cycle;
}
if (first) {
first = FALSE;
lin = linear;
d = origd = screen_desktop;
}
get_row_col(d, &r, &c);
if (lin) {
g_message("linear %d", d);
switch (dir) {
case OB_DIRECTION_EAST:
if (d < screen_num_desktops - 1)
++d;
else if (wrap)
d = 0;
break;
case OB_DIRECTION_WEST:
if (d > 0)
--d;
else if (wrap)
d = screen_num_desktops - 1;
break;
default:
assert(0);
return screen_desktop;
}
g_message("linear %d done", d);
} else {
switch (dir) {
case OB_DIRECTION_EAST:
++c;
if (c >= screen_desktop_layout.columns) {
if (!wrap) return d = screen_desktop;
c = 0;
}
d = translate_row_col(r, c);
if (d >= screen_num_desktops) {
if (!wrap) return d = screen_desktop;
++c;
}
break;
case OB_DIRECTION_WEST:
--c;
if (c >= screen_desktop_layout.columns) {
if (!wrap) return d = screen_desktop;
c = screen_desktop_layout.columns - 1;
}
d = translate_row_col(r, c);
if (d >= screen_num_desktops) {
if (!wrap) return d = screen_desktop;
--c;
}
break;
case OB_DIRECTION_SOUTH:
++r;
if (r >= screen_desktop_layout.rows) {
if (!wrap) return d = screen_desktop;
r = 0;
}
d = translate_row_col(r, c);
if (d >= screen_num_desktops) {
if (!wrap) return d = screen_desktop;
++r;
}
break;
case OB_DIRECTION_NORTH:
--r;
if (r >= screen_desktop_layout.rows) {
if (!wrap) return d = screen_desktop;
r = screen_desktop_layout.rows - 1;
}
d = translate_row_col(r, c);
if (d >= screen_num_desktops) {
if (!wrap) return d = screen_desktop;
--r;
}
break;
default:
assert(0);
return d = screen_desktop;
}
d = translate_row_col(r, c);
}
popup_cycle(d, TRUE);
return d;
done_cycle:
first = TRUE;
popup_cycle(0, FALSE);
return d = screen_desktop;
}
void screen_update_layout() void screen_update_layout()
{ {
ObOrientation orient; ObOrientation orient;

View file

@ -45,6 +45,9 @@ void screen_resize();
void screen_set_num_desktops(guint num); void screen_set_num_desktops(guint num);
/*! Change the current desktop */ /*! Change the current desktop */
void screen_set_desktop(guint num); void screen_set_desktop(guint num);
/*! Interactively change desktops */
guint screen_cycle_desktop(ObDirection dir, gboolean wrap, gboolean linear,
gboolean done, gboolean cancel);
/*! Shows and focuses the desktop and hides all the client windows, or /*! Shows and focuses the desktop and hides all the client windows, or
returns to the normal state, showing client windows. */ returns to the normal state, showing client windows. */

View file

@ -63,3 +63,47 @@ translation_fail:
g_strfreev(parsed); g_strfreev(parsed);
return ret; return ret;
} }
gboolean translate_key(char *str, guint *state, guint *keycode)
{
char **parsed;
char *l;
int i;
gboolean ret = FALSE;
KeySym sym;
parsed = g_strsplit(str, "-", -1);
/* first, find the key (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 keycode */
sym = XStringToKeysym(l);
if (sym == NoSymbol) {
g_warning("Invalid key name '%s' in key binding.", l);
goto translation_fail;
}
*keycode = XKeysymToKeycode(ob_display, sym);
if (!*keycode) {
g_warning("Key '%s' does not exist on the display.", l);
goto translation_fail;
}
ret = TRUE;
translation_fail:
g_strfreev(parsed);
return ret;
}

9
openbox/translate.h Normal file
View file

@ -0,0 +1,9 @@
#ifndef ob__translate_h
#define ob__translate_h
#include <glib.h>
gboolean translate_button(gchar *str, guint *state, guint *keycode);
gboolean translate_key(gchar *str, guint *state, guint *keycode);
#endif

View file

@ -52,7 +52,7 @@ void client_send_to_update(ObMenu *self)
ob_debug("update\n"); ob_debug("update\n");
for (i = 0; i < screen_num_desktops; ++i) { for (i = 0; i < screen_num_desktops; ++i) {
ObMenuEntry *e; ObMenuEntry *e;
Action *a = action_from_string("sendtodesktop"); ObAction *a = action_from_string("sendtodesktop");
a->data.sendto.desk = i; a->data.sendto.desk = i;
a->data.sendto.follow = FALSE; a->data.sendto.follow = FALSE;
e = menu_entry_new(screen_desktop_names[i], a); e = menu_entry_new(screen_desktop_names[i], a);

View file

@ -1,6 +0,0 @@
mouse.la
.libs
.deps
.dirstamp
plugins_mouse_mouse_la-mouse.lo
plugins_mouse_mouse_la-translate.lo

View file

@ -1,4 +0,0 @@
all clean install:
$(MAKE) -C ../.. -$(MAKEFLAGS) $@
.PHONY: all clean install

View file

@ -1,24 +0,0 @@
#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;
GSList *actions[NUM_MOUSEACTION]; /* lists of Action pointers */
} MouseBinding;
gboolean mbind(char *buttonstr, char *contextstr, MouseAction mact,
Action *action);
#endif

View file

@ -1,8 +0,0 @@
#ifndef __plugin_mouse_translate_h
#define __plugin_mouse_translate_h
#include <glib.h>
gboolean translate_button(char *str, guint *state, guint *keycode);
#endif