Merge branch 'backport' into work

Conflicts:

	obt/keyboard.c
	obt/keyboard.h
	openbox/event.c
	openbox/menuframe.c
	openbox/moveresize.c
	openbox/openbox.c
	openbox/screen.c
This commit is contained in:
Dana Jansens 2009-12-16 15:39:25 -05:00
commit 50d6626811
16 changed files with 249 additions and 173 deletions

View file

@ -185,16 +185,24 @@ static void set_modkey_mask(guchar mask, KeySym sym)
/* CapsLock, Shift, and Control are special and hard-coded */ /* CapsLock, Shift, and Control are special and hard-coded */
} }
KeyCode obt_keyboard_keysym_to_keycode(KeySym sym) KeyCode* obt_keyboard_keysym_to_keycode(KeySym sym)
{ {
gint i, j; KeyCode *ret;
gint i, j, n;
ret = g_new(KeyCode, 1);
n = 0;
ret[n] = 0;
/* go through each keycode and look for the keysym */ /* go through each keycode and look for the keysym */
for (i = min_keycode; i <= max_keycode; ++i) for (i = min_keycode; i <= max_keycode; ++i)
for (j = 0; j < keysyms_per_keycode; ++j) for (j = 0; j < keysyms_per_keycode; ++j)
if (sym == keymap[(i-min_keycode) * keysyms_per_keycode + j]) if (sym == keymap[(i-min_keycode) * keysyms_per_keycode + j]) {
return i; ret = g_renew(KeyCode, ret, ++n);
return 0; ret[n-1] = i;
ret[n] = 0;
}
return ret;
} }
gchar *obt_keyboard_keycode_to_string(guint keycode) gchar *obt_keyboard_keycode_to_string(guint keycode)

View file

@ -54,9 +54,8 @@ guint obt_keyboard_only_modmasks(guint mask);
right keys when there are both. */ right keys when there are both. */
guint obt_keyboard_modkey_to_modmask(ObtModkeysKey key); guint obt_keyboard_modkey_to_modmask(ObtModkeysKey key);
/*! Convert a KeySym to a KeyCode, because the X function is terrible - says /*! Convert a KeySym to all the KeyCodes which generate it. */
valgrind. */ KeyCode* obt_keyboard_keysym_to_keycode(KeySym sym);
KeyCode obt_keyboard_keysym_to_keycode(KeySym sym);
/*! Give the string form of a KeyCode */ /*! Give the string form of a KeyCode */
gchar *obt_keyboard_keycode_to_string(guint keycode); gchar *obt_keyboard_keycode_to_string(guint keycode);

View file

@ -146,13 +146,13 @@ static gboolean i_input_func(guint initial_state,
{ {
if (e->type == KeyPress) { if (e->type == KeyPress) {
/* Escape cancels no matter what */ /* Escape cancels no matter what */
if (e->xkey.keycode == ob_keycode(OB_KEY_ESCAPE)) { if (ob_keycode_match(e->xkey.keycode, OB_KEY_ESCAPE)) {
end_cycle(TRUE, e->xkey.state, options); end_cycle(TRUE, e->xkey.state, options);
return FALSE; return FALSE;
} }
/* There were no modifiers and they pressed enter */ /* There were no modifiers and they pressed enter */
else if (e->xkey.keycode == ob_keycode(OB_KEY_RETURN) && else if (ob_keycode_match(e->xkey.keycode, OB_KEY_RETURN) &&
!initial_state) !initial_state)
{ {
end_cycle(FALSE, e->xkey.state, options); end_cycle(FALSE, e->xkey.state, options);

View file

@ -216,13 +216,13 @@ static gboolean i_input_func(guint initial_state,
{ {
if (e->type == KeyPress) { if (e->type == KeyPress) {
/* Escape cancels no matter what */ /* Escape cancels no matter what */
if (e->xkey.keycode == ob_keycode(OB_KEY_ESCAPE)) { if (ob_keycode_match(e->xkey.keycode, OB_KEY_ESCAPE)) {
end_cycle(TRUE, e->xkey.state, options); end_cycle(TRUE, e->xkey.state, options);
return FALSE; return FALSE;
} }
/* There were no modifiers and they pressed enter */ /* There were no modifiers and they pressed enter */
else if (e->xkey.keycode == ob_keycode(OB_KEY_RETURN) && else if (ob_keycode_match(e->xkey.keycode, OB_KEY_RETURN) &&
!initial_state) !initial_state)
{ {
end_cycle(FALSE, e->xkey.state, options); end_cycle(FALSE, e->xkey.state, options);

View file

@ -1751,30 +1751,30 @@ static gboolean event_handle_menu_input(XEvent *ev)
else if (ev->type == KeyPress && (state & ~ControlMask) == 0) { else if (ev->type == KeyPress && (state & ~ControlMask) == 0) {
frame->got_press = TRUE; frame->got_press = TRUE;
if (keycode == ob_keycode(OB_KEY_ESCAPE)) { if (ob_keycode_match(keycode, OB_KEY_ESCAPE)) {
menu_frame_hide_all(); menu_frame_hide_all();
ret = TRUE; ret = TRUE;
} }
else if (keycode == ob_keycode(OB_KEY_LEFT)) { else if (ob_keycode_match(keycode, OB_KEY_LEFT)) {
/* Left goes to the parent menu */ /* Left goes to the parent menu */
if (frame->parent) if (frame->parent)
menu_frame_select(frame, NULL, TRUE); menu_frame_select(frame, NULL, TRUE);
ret = TRUE; ret = TRUE;
} }
else if (keycode == ob_keycode(OB_KEY_RIGHT)) { else if (ob_keycode_match(keycode, OB_KEY_RIGHT)) {
/* Right goes to the selected submenu */ /* Right goes to the selected submenu */
if (frame->child) menu_frame_select_next(frame->child); if (frame->child) menu_frame_select_next(frame->child);
ret = TRUE; ret = TRUE;
} }
else if (keycode == ob_keycode(OB_KEY_UP)) { else if (ob_keycode_match(keycode, OB_KEY_UP)) {
menu_frame_select_previous(frame); menu_frame_select_previous(frame);
ret = TRUE; ret = TRUE;
} }
else if (keycode == ob_keycode(OB_KEY_DOWN)) { else if (ob_keycode_match(keycode, OB_KEY_DOWN)) {
menu_frame_select_next(frame); menu_frame_select_next(frame);
ret = TRUE; ret = TRUE;
} }
@ -1787,7 +1787,7 @@ static gboolean event_handle_menu_input(XEvent *ev)
else if (ev->type == KeyRelease && (state & ~ControlMask) == 0 && else if (ev->type == KeyRelease && (state & ~ControlMask) == 0 &&
frame->entries && frame->got_press) frame->entries && frame->got_press)
{ {
if (keycode == ob_keycode(OB_KEY_RETURN)) { if (ob_keycode_match(keycode, OB_KEY_RETURN)) {
/* Enter runs the active item or goes into the submenu. /* Enter runs the active item or goes into the submenu.
Control-Enter runs it without closing the menu. */ Control-Enter runs it without closing the menu. */
if (frame->child) if (frame->child)
@ -1885,7 +1885,12 @@ static void event_handle_menu(ObMenuFrame *frame, XEvent *ev)
(f = find_active_menu()) && f->selected == e && (f = find_active_menu()) && f->selected == e &&
e->entry->type != OB_MENU_ENTRY_TYPE_SUBMENU) e->entry->type != OB_MENU_ENTRY_TYPE_SUBMENU)
{ {
menu_frame_select(e->frame, NULL, FALSE); ObMenuEntryFrame *u = menu_entry_frame_under(ev->xcrossing.x_root,
ev->xcrossing.y_root);
/* if we're just going from one entry in the menu to the next,
don't unselect stuff first */
if (!u || e->frame != u->frame)
menu_frame_select(e->frame, NULL, FALSE);
} }
break; break;
} }

View file

@ -351,7 +351,7 @@ static void popup_render(ObFocusCyclePopup *p, const ObClient *c)
g_assert(mode == OB_FOCUS_CYCLE_POPUP_MODE_ICONS || g_assert(mode == OB_FOCUS_CYCLE_POPUP_MODE_ICONS ||
mode == OB_FOCUS_CYCLE_POPUP_MODE_LIST); mode == OB_FOCUS_CYCLE_POPUP_MODE_LIST);
screen_area = screen_physical_area_primary(); screen_area = screen_physical_area_primary(FALSE);
/* get the outside margins */ /* get the outside margins */
RrMargins(p->a_bg, &ml, &mt, &mr, &mb); RrMargins(p->a_bg, &ml, &mt, &mr, &mb);
@ -715,7 +715,7 @@ void focus_cycle_popup_single_show(struct _ObClient *c,
g_assert(popup.targets == NULL); g_assert(popup.targets == NULL);
/* position the popup */ /* position the popup */
a = screen_physical_area_primary(); a = screen_physical_area_primary(FALSE);
icon_popup_position(single_popup, CenterGravity, icon_popup_position(single_popup, CenterGravity,
a->x + a->width / 2, a->y + a->height / 2); a->x + a->width / 2, a->y + a->height / 2);
icon_popup_height(single_popup, POPUP_HEIGHT); icon_popup_height(single_popup, POPUP_HEIGHT);

View file

@ -89,7 +89,7 @@ static void set_curpos(KeyBindingTree *newpos)
g_free(oldtext); g_free(oldtext);
} }
a = screen_physical_area_primary(); a = screen_physical_area_primary(FALSE);
popup_position(popup, NorthWestGravity, a->x + 10, a->y + 10); popup_position(popup, NorthWestGravity, a->x + 10, a->y + 10);
/* 1 second delay for the popup to show */ /* 1 second delay for the popup to show */
popup_delay_show(popup, G_USEC_PER_SEC, text); popup_delay_show(popup, G_USEC_PER_SEC, text);

View file

@ -22,6 +22,7 @@
#include "menu.h" #include "menu.h"
#include "screen.h" #include "screen.h"
#include "actions.h" #include "actions.h"
#include "event.h"
#include "grab.h" #include "grab.h"
#include "openbox.h" #include "openbox.h"
#include "config.h" #include "config.h"
@ -47,7 +48,8 @@ static ObMenuEntryFrame* menu_entry_frame_new(ObMenuEntry *entry,
ObMenuFrame *frame); ObMenuFrame *frame);
static void menu_entry_frame_free(ObMenuEntryFrame *self); static void menu_entry_frame_free(ObMenuEntryFrame *self);
static void menu_frame_update(ObMenuFrame *self); static void menu_frame_update(ObMenuFrame *self);
static gboolean menu_entry_frame_submenu_timeout(gpointer data); static gboolean menu_entry_frame_submenu_hide_timeout(gpointer data);
static gboolean menu_entry_frame_submenu_show_timeout(gpointer data);
static void menu_frame_hide(ObMenuFrame *self); static void menu_frame_hide(ObMenuFrame *self);
static Window createWindow(Window parent, gulong mask, static Window createWindow(Window parent, gulong mask,
@ -93,6 +95,7 @@ ObMenuFrame* menu_frame_new(ObMenu *menu, guint show_from, ObClient *client)
self->obwin.type = OB_WINDOW_CLASS_MENUFRAME; self->obwin.type = OB_WINDOW_CLASS_MENUFRAME;
self->menu = menu; self->menu = menu;
self->selected = NULL; self->selected = NULL;
self->open_submenu = NULL;
self->client = client; self->client = client;
self->direction_right = TRUE; self->direction_right = TRUE;
self->show_from = show_from; self->show_from = show_from;
@ -197,6 +200,7 @@ static void menu_entry_frame_free(ObMenuEntryFrame *self)
void menu_frame_move(ObMenuFrame *self, gint x, gint y) void menu_frame_move(ObMenuFrame *self, gint x, gint y)
{ {
RECT_SET_POINT(self->area, x, y); RECT_SET_POINT(self->area, x, y);
self->monitor = screen_find_monitor_point(x, y);
XMoveWindow(obt_display, self->window, self->area.x, self->area.y); XMoveWindow(obt_display, self->window, self->area.x, self->area.y);
} }
@ -299,7 +303,7 @@ void menu_frame_move_on_screen(ObMenuFrame *self, gint x, gint y,
*dx = *dy = 0; *dx = *dy = 0;
a = screen_physical_area_monitor(self->monitor); a = screen_physical_area_monitor(screen_find_monitor_point(x, y));
half = g_list_length(self->entries) / 2; half = g_list_length(self->entries) / 2;
pos = g_list_index(self->entries, self->selected); pos = g_list_index(self->entries, self->selected);
@ -957,24 +961,12 @@ gboolean menu_frame_show_topmenu(ObMenuFrame *self, gint x, gint y,
gboolean mouse) gboolean mouse)
{ {
gint px, py; gint px, py;
guint i;
if (menu_frame_is_visible(self)) if (menu_frame_is_visible(self))
return TRUE; return TRUE;
if (!menu_frame_show(self)) if (!menu_frame_show(self))
return FALSE; return FALSE;
/* find the monitor the menu is on */
for (i = 0; i < screen_num_monitors; ++i) {
Rect *a = screen_physical_area_monitor(i);
gboolean contains = RECT_CONTAINS(*a, x, y);
g_free(a);
if (contains) {
self->monitor = i;
break;
}
}
if (self->menu->place_func) if (self->menu->place_func)
self->menu->place_func(self, &x, &y, mouse, self->menu->data); self->menu->place_func(self, &x, &y, mouse, self->menu->data);
else else
@ -1005,6 +997,7 @@ gboolean menu_frame_show_submenu(ObMenuFrame *self, ObMenuFrame *parent,
self->monitor = parent->monitor; self->monitor = parent->monitor;
self->parent = parent; self->parent = parent;
self->parent_entry = parent_entry; self->parent_entry = parent_entry;
parent->open_submenu = parent_entry;
/* set up parent's child to be us */ /* set up parent's child to be us */
if (parent->child) if (parent->child)
@ -1039,6 +1032,7 @@ gboolean menu_frame_show_submenu(ObMenuFrame *self, ObMenuFrame *parent,
static void menu_frame_hide(ObMenuFrame *self) static void menu_frame_hide(ObMenuFrame *self)
{ {
GList *it = g_list_find(menu_frame_visible, self); GList *it = g_list_find(menu_frame_visible, self);
gulong ignore_start;
if (!it) if (!it)
return; return;
@ -1049,8 +1043,10 @@ static void menu_frame_hide(ObMenuFrame *self)
if (self->child) if (self->child)
menu_frame_hide(self->child); menu_frame_hide(self->child);
if (self->parent) if (self->parent && self->parent->child == self) {
self->parent->child = NULL; self->parent->child = NULL;
self->parent->open_submenu = NULL;
}
self->parent = NULL; self->parent = NULL;
self->parent_entry = NULL; self->parent_entry = NULL;
@ -1062,7 +1058,9 @@ static void menu_frame_hide(ObMenuFrame *self)
ungrab_keyboard(); ungrab_keyboard();
} }
ignore_start = event_start_ignore_all_enters();
XUnmapWindow(obt_display, self->window); XUnmapWindow(obt_display, self->window);
event_end_ignore_all_enters(ignore_start);
menu_frame_free(self); menu_frame_free(self);
} }
@ -1074,7 +1072,10 @@ void menu_frame_hide_all(void)
if (config_submenu_show_delay) { if (config_submenu_show_delay) {
/* remove any submenu open requests */ /* remove any submenu open requests */
obt_main_loop_timeout_remove(ob_main_loop, obt_main_loop_timeout_remove(ob_main_loop,
menu_entry_frame_submenu_timeout); menu_entry_frame_submenu_show_timeout);
/* remove any submenu close delays */
obt_main_loop_timeout_remove(ob_main_loop,
menu_entry_frame_submenu_hide_timeout);
} }
if ((it = g_list_last(menu_frame_visible))) if ((it = g_list_last(menu_frame_visible)))
menu_frame_hide(it->data); menu_frame_hide(it->data);
@ -1088,8 +1089,13 @@ void menu_frame_hide_all_client(ObClient *client)
if (f->client == client) { if (f->client == client) {
if (config_submenu_show_delay) { if (config_submenu_show_delay) {
/* remove any submenu open requests */ /* remove any submenu open requests */
obt_main_loop_timeout_remove(ob_main_loop, obt_main_loop_timeout_remove
menu_entry_frame_submenu_timeout); (ob_main_loop,
menu_entry_frame_submenu_show_timeout);
/* remove any submenu close delays */
obt_main_loop_timeout_remove
(ob_main_loop,
menu_entry_frame_submenu_hide_timeout);
} }
menu_frame_hide(f); menu_frame_hide(f);
} }
@ -1124,7 +1130,6 @@ ObMenuEntryFrame* menu_entry_frame_under(gint x, gint y)
for (it = frame->entries; it; it = g_list_next(it)) { for (it = frame->entries; it; it = g_list_next(it)) {
ObMenuEntryFrame *e = it->data; ObMenuEntryFrame *e = it->data;
if (RECT_CONTAINS(e->area, x, y)) { if (RECT_CONTAINS(e->area, x, y)) {
ret = e; ret = e;
break; break;
@ -1134,7 +1139,15 @@ ObMenuEntryFrame* menu_entry_frame_under(gint x, gint y)
return ret; return ret;
} }
static gboolean menu_entry_frame_submenu_timeout(gpointer data) static gboolean menu_entry_frame_submenu_hide_timeout(gpointer data)
{
g_assert(menu_frame_visible);
g_assert(((ObMenuFrame*)data)->parent != NULL);
menu_frame_hide((ObMenuFrame*)data);
return FALSE;
}
static gboolean menu_entry_frame_submenu_show_timeout(gpointer data)
{ {
g_assert(menu_frame_visible); g_assert(menu_frame_visible);
menu_entry_frame_show_submenu((ObMenuEntryFrame*)data); menu_entry_frame_show_submenu((ObMenuEntryFrame*)data);
@ -1155,27 +1168,67 @@ void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry,
if (config_submenu_show_delay) { if (config_submenu_show_delay) {
/* remove any submenu open requests */ /* remove any submenu open requests */
obt_main_loop_timeout_remove(ob_main_loop, obt_main_loop_timeout_remove(ob_main_loop,
menu_entry_frame_submenu_timeout); menu_entry_frame_submenu_show_timeout);
}
if (!entry && self->open_submenu) {
/* we moved out of the menu, so move the selection back to the open
submenu */
entry = self->open_submenu;
oldchild = NULL;
/* remove any submenu close delays */
obt_main_loop_timeout_remove(ob_main_loop,
menu_entry_frame_submenu_hide_timeout);
} }
self->selected = entry; self->selected = entry;
if (old) if (old)
menu_entry_frame_render(old); menu_entry_frame_render(old);
if (oldchild)
menu_frame_hide(oldchild); if (oldchild) {
/* there is an open submenu */
if (config_submenu_show_delay && !immediate) {
if (entry == self->open_submenu) {
/* we moved onto the entry that has an open submenu, so stop
trying to close the submenu */
obt_main_loop_timeout_remove
(ob_main_loop,
menu_entry_frame_submenu_hide_timeout);
}
else if (old == self->open_submenu) {
/* we just moved off the entry with an open submenu, so
close the open submenu after a delay */
obt_main_loop_timeout_add
(ob_main_loop,
config_submenu_show_delay * 1000,
menu_entry_frame_submenu_hide_timeout,
self->child, g_direct_equal,
NULL);
}
}
else
menu_frame_hide(oldchild);
}
if (self->selected) { if (self->selected) {
menu_entry_frame_render(self->selected); menu_entry_frame_render(self->selected);
if (self->selected->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU) { /* if we've selected a submenu and it wasn't already open, then
show it */
if (self->selected->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU &&
self->selected != self->open_submenu)
{
if (config_submenu_show_delay && !immediate) { if (config_submenu_show_delay && !immediate) {
/* initiate a new submenu open request */ /* initiate a new submenu open request */
obt_main_loop_timeout_add(ob_main_loop, obt_main_loop_timeout_add
config_submenu_show_delay * 1000, (ob_main_loop,
menu_entry_frame_submenu_timeout, config_submenu_show_delay * 1000,
self->selected, g_direct_equal, menu_entry_frame_submenu_show_timeout,
NULL); self->selected, g_direct_equal,
NULL);
} else { } else {
menu_entry_frame_show_submenu(self->selected); menu_entry_frame_show_submenu(self->selected);
} }

View file

@ -53,6 +53,9 @@ struct _ObMenuFrame
GList *entries; GList *entries;
ObMenuEntryFrame *selected; ObMenuEntryFrame *selected;
/* if a submenu was selected, then this holds the entry for that submenu
until it is closed */
ObMenuEntryFrame *open_submenu;
/* show entries from the menu starting at this index */ /* show entries from the menu starting at this index */
guint show_from; guint show_from;

View file

@ -605,13 +605,13 @@ static void move_with_keys(gint keycode, gint state)
gint x, y; gint x, y;
ObDirection dir; ObDirection dir;
if (keycode == ob_keycode(OB_KEY_RIGHT)) if (ob_keycode_match(keycode, OB_KEY_RIGHT))
dir = OB_DIRECTION_EAST; dir = OB_DIRECTION_EAST;
else if (keycode == ob_keycode(OB_KEY_LEFT)) else if (ob_keycode_match(keycode, OB_KEY_LEFT))
dir = OB_DIRECTION_WEST; dir = OB_DIRECTION_WEST;
else if (keycode == ob_keycode(OB_KEY_DOWN)) else if (ob_keycode_match(keycode, OB_KEY_DOWN))
dir = OB_DIRECTION_SOUTH; dir = OB_DIRECTION_SOUTH;
else /* if (keycode == ob_keycode(OB_KEY_UP)) */ else /* if (ob_keycode_match(keycode, OB_KEY_UP)) */
dir = OB_DIRECTION_NORTH; dir = OB_DIRECTION_NORTH;
client_find_move_directional(moveresize_client, dir, &x, &y); client_find_move_directional(moveresize_client, dir, &x, &y);
@ -627,13 +627,13 @@ static void move_with_keys(gint keycode, gint state)
else else
dist = KEY_DIST; dist = KEY_DIST;
if (keycode == ob_keycode(OB_KEY_RIGHT)) if (ob_keycode_match(keycode, OB_KEY_RIGHT))
dx = dist; dx = dist;
else if (keycode == ob_keycode(OB_KEY_LEFT)) else if (ob_keycode_match(keycode, OB_KEY_LEFT))
dx = -dist; dx = -dist;
else if (keycode == ob_keycode(OB_KEY_DOWN)) else if (ob_keycode_match(keycode, OB_KEY_DOWN))
dy = dist; dy = dist;
else /* if (keycode == ob_keycode(OB_KEY_UP)) */ else /* if (ob_keycode_match(keycode, OB_KEY_UP)) */
dy = -dist; dy = -dist;
} }
@ -666,7 +666,7 @@ static void resize_with_keys(gint keycode, gint state)
ObDirection dir; ObDirection dir;
/* pick the edge if it needs to move */ /* pick the edge if it needs to move */
if (keycode == ob_keycode(OB_KEY_RIGHT)) { if (ob_keycode_match(keycode, OB_KEY_RIGHT)) {
dir = OB_DIRECTION_EAST; dir = OB_DIRECTION_EAST;
if (key_resize_edge != OB_DIRECTION_WEST && if (key_resize_edge != OB_DIRECTION_WEST &&
key_resize_edge != OB_DIRECTION_EAST) key_resize_edge != OB_DIRECTION_EAST)
@ -674,7 +674,7 @@ static void resize_with_keys(gint keycode, gint state)
key_resize_edge = OB_DIRECTION_EAST; key_resize_edge = OB_DIRECTION_EAST;
return; return;
} }
} else if (keycode == ob_keycode(OB_KEY_LEFT)) { } else if (ob_keycode_match(keycode, OB_KEY_LEFT)) {
dir = OB_DIRECTION_WEST; dir = OB_DIRECTION_WEST;
if (key_resize_edge != OB_DIRECTION_WEST && if (key_resize_edge != OB_DIRECTION_WEST &&
key_resize_edge != OB_DIRECTION_EAST) key_resize_edge != OB_DIRECTION_EAST)
@ -682,7 +682,7 @@ static void resize_with_keys(gint keycode, gint state)
key_resize_edge = OB_DIRECTION_WEST; key_resize_edge = OB_DIRECTION_WEST;
return; return;
} }
} else if (keycode == ob_keycode(OB_KEY_UP)) { } else if (ob_keycode_match(keycode, OB_KEY_UP)) {
dir = OB_DIRECTION_NORTH; dir = OB_DIRECTION_NORTH;
if (key_resize_edge != OB_DIRECTION_NORTH && if (key_resize_edge != OB_DIRECTION_NORTH &&
key_resize_edge != OB_DIRECTION_SOUTH) key_resize_edge != OB_DIRECTION_SOUTH)
@ -690,7 +690,7 @@ static void resize_with_keys(gint keycode, gint state)
key_resize_edge = OB_DIRECTION_NORTH; key_resize_edge = OB_DIRECTION_NORTH;
return; return;
} }
} else /* if (keycode == ob_keycode(OB_KEY_DOWN)) */ { } else /* if (ob_keycode_match(keycode, OB_KEY_DOWN)) */ {
dir = OB_DIRECTION_SOUTH; dir = OB_DIRECTION_SOUTH;
if (key_resize_edge != OB_DIRECTION_NORTH && if (key_resize_edge != OB_DIRECTION_NORTH &&
key_resize_edge != OB_DIRECTION_SOUTH) key_resize_edge != OB_DIRECTION_SOUTH)
@ -704,13 +704,13 @@ static void resize_with_keys(gint keycode, gint state)
if (state & obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_SHIFT)) { if (state & obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_SHIFT)) {
gint x, y, w, h; gint x, y, w, h;
if (keycode == ob_keycode(OB_KEY_RIGHT)) if (ob_keycode_match(keycode, OB_KEY_RIGHT))
dir = OB_DIRECTION_EAST; dir = OB_DIRECTION_EAST;
else if (keycode == ob_keycode(OB_KEY_LEFT)) else if (ob_keycode_match(keycode, OB_KEY_LEFT))
dir = OB_DIRECTION_WEST; dir = OB_DIRECTION_WEST;
else if (keycode == ob_keycode(OB_KEY_DOWN)) else if (ob_keycode_match(keycode, OB_KEY_DOWN))
dir = OB_DIRECTION_SOUTH; dir = OB_DIRECTION_SOUTH;
else /* if (keycode == ob_keycode(OB_KEY_UP)) */ else /* if (ob_keycode_match(keycode, OB_KEY_UP)) */
dir = OB_DIRECTION_NORTH; dir = OB_DIRECTION_NORTH;
client_find_resize_directional(moveresize_client, key_resize_edge, client_find_resize_directional(moveresize_client, key_resize_edge,
@ -912,16 +912,16 @@ gboolean moveresize_event(XEvent *e)
} }
used = TRUE; used = TRUE;
} else if (e->type == KeyPress) { } else if (e->type == KeyPress) {
if (e->xkey.keycode == ob_keycode(OB_KEY_ESCAPE)) { if (ob_keycode_match(e->xkey.keycode, OB_KEY_ESCAPE)) {
moveresize_end(TRUE); moveresize_end(TRUE);
used = TRUE; used = TRUE;
} else if (e->xkey.keycode == ob_keycode(OB_KEY_RETURN)) { } else if (ob_keycode_match(e->xkey.keycode, OB_KEY_RETURN)) {
moveresize_end(FALSE); moveresize_end(FALSE);
used = TRUE; used = TRUE;
} else if (e->xkey.keycode == ob_keycode(OB_KEY_RIGHT) || } else if (ob_keycode_match(e->xkey.keycode, OB_KEY_RIGHT) ||
e->xkey.keycode == ob_keycode(OB_KEY_LEFT) || ob_keycode_match(e->xkey.keycode, OB_KEY_LEFT) ||
e->xkey.keycode == ob_keycode(OB_KEY_DOWN) || ob_keycode_match(e->xkey.keycode, OB_KEY_DOWN) ||
e->xkey.keycode == ob_keycode(OB_KEY_UP)) ob_keycode_match(e->xkey.keycode, OB_KEY_UP))
{ {
if (corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_KEYBOARD)) { if (corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_KEYBOARD)) {
resize_with_keys(e->xkey.keycode, e->xkey.state); resize_with_keys(e->xkey.keycode, e->xkey.state);

View file

@ -101,7 +101,7 @@ static gboolean reconfigure = FALSE;
static gboolean restart = FALSE; static gboolean restart = FALSE;
static gchar *restart_path = NULL; static gchar *restart_path = NULL;
static Cursor cursors[OB_NUM_CURSORS]; static Cursor cursors[OB_NUM_CURSORS];
static KeyCode keys[OB_NUM_KEYS]; static KeyCode *keys[OB_NUM_KEYS];
static gint exitcode = 0; static gint exitcode = 0;
static guint remote_control = 0; static guint remote_control = 0;
static gboolean being_replaced = FALSE; static gboolean being_replaced = FALSE;
@ -400,6 +400,16 @@ gint main(gint argc, gchar **argv)
event_shutdown(reconfigure); event_shutdown(reconfigure);
config_shutdown(); config_shutdown();
actions_shutdown(reconfigure); actions_shutdown(reconfigure);
/* Free the key codes for built in keys */
g_free(keys[OB_KEY_RETURN]);
g_free(keys[OB_KEY_ESCAPE]);
g_free(keys[OB_KEY_LEFT]);
g_free(keys[OB_KEY_RIGHT]);
g_free(keys[OB_KEY_UP]);
g_free(keys[OB_KEY_DOWN]);
g_free(keys[OB_KEY_TAB]);
g_free(keys[OB_KEY_SPACE]);
} while (reconfigure); } while (reconfigure);
} }
@ -716,10 +726,14 @@ Cursor ob_cursor(ObCursor cursor)
return cursors[cursor]; return cursors[cursor];
} }
KeyCode ob_keycode(ObKey key) gboolean ob_keycode_match(KeyCode code, ObKey key)
{ {
KeyCode *k;
g_assert(key < OB_NUM_KEYS); g_assert(key < OB_NUM_KEYS);
return keys[key]; for (k = keys[key]; *k; ++k)
if (*k == code) return TRUE;
return FALSE;
} }
ObState ob_state(void) ObState ob_state(void)

View file

@ -62,6 +62,6 @@ void ob_exit_with_error(const gchar *msg) G_GNUC_NORETURN;
Cursor ob_cursor(ObCursor cursor); Cursor ob_cursor(ObCursor cursor);
KeyCode ob_keycode(ObKey key); gboolean ob_keycode_match(KeyCode code, ObKey key);
#endif #endif

View file

@ -531,23 +531,23 @@ gboolean prompt_key_event(ObPrompt *self, XEvent *e)
if (e->xkey.state != 0 && e->xkey.state != shift_mask) if (e->xkey.state != 0 && e->xkey.state != shift_mask)
return FALSE; return FALSE;
if (e->xkey.keycode == ob_keycode(OB_KEY_ESCAPE)) if (ob_keycode_match(e->xkey.keycode, OB_KEY_ESCAPE))
prompt_cancel(self); prompt_cancel(self);
else if (e->xkey.keycode == ob_keycode(OB_KEY_RETURN) || else if (ob_keycode_match(e->xkey.keycode, OB_KEY_RETURN) ||
e->xkey.keycode == ob_keycode(OB_KEY_SPACE)) ob_keycode_match(e->xkey.keycode, OB_KEY_SPACE))
{ {
prompt_run_callback(self, self->focus->result); prompt_run_callback(self, self->focus->result);
} }
else if (e->xkey.keycode == ob_keycode(OB_KEY_TAB) || else if (ob_keycode_match(e->xkey.keycode, OB_KEY_TAB) ||
e->xkey.keycode == ob_keycode(OB_KEY_LEFT) || ob_keycode_match(e->xkey.keycode, OB_KEY_LEFT) ||
e->xkey.keycode == ob_keycode(OB_KEY_RIGHT)) ob_keycode_match(e->xkey.keycode, OB_KEY_RIGHT))
{ {
gint i; gint i;
gboolean left; gboolean left;
ObPromptElement *oldfocus; ObPromptElement *oldfocus;
left = e->xkey.keycode == ob_keycode(OB_KEY_LEFT) || left = ob_keycode_match(e->xkey.keycode, OB_KEY_LEFT) ||
(e->xkey.keycode == ob_keycode(OB_KEY_TAB) && shift); (ob_keycode_match(e->xkey.keycode, OB_KEY_TAB) && shift);
oldfocus = self->focus; oldfocus = self->focus;
for (i = 0; i < self->n_buttons; ++i) for (i = 0; i < self->n_buttons; ++i)

View file

@ -929,7 +929,7 @@ void screen_show_desktop_popup(guint d)
/* 0 means don't show the popup */ /* 0 means don't show the popup */
if (!config_desktop_popup_time) return; if (!config_desktop_popup_time) return;
a = screen_physical_area_primary(); a = screen_physical_area_primary(FALSE);
pager_popup_position(desktop_popup, CenterGravity, pager_popup_position(desktop_popup, CenterGravity,
a->x + a->width / 2, a->y + a->height / 2); a->x + a->width / 2, a->y + a->height / 2);
pager_popup_icon_size_multiplier(desktop_popup, pager_popup_icon_size_multiplier(desktop_popup,
@ -1270,19 +1270,6 @@ void screen_install_colormap(ObClient *client, gboolean install)
} }
} }
#define STRUT_LEFT_ON_MONITOR(s, i) \
(RANGES_INTERSECT(s->left_start, s->left_end - s->left_start + 1, \
monitor_area[i].y, monitor_area[i].height))
#define STRUT_RIGHT_ON_MONITOR(s, i) \
(RANGES_INTERSECT(s->right_start, s->right_end - s->right_start + 1, \
monitor_area[i].y, monitor_area[i].height))
#define STRUT_TOP_ON_MONITOR(s, i) \
(RANGES_INTERSECT(s->top_start, s->top_end - s->top_start + 1, \
monitor_area[i].x, monitor_area[i].width))
#define STRUT_BOTTOM_ON_MONITOR(s, i) \
(RANGES_INTERSECT(s->bottom_start, s->bottom_end - s->bottom_start + 1, \
monitor_area[i].x, monitor_area[i].width))
typedef struct { typedef struct {
guint desktop; guint desktop;
StrutPartial *strut; StrutPartial *strut;
@ -1359,7 +1346,7 @@ static void get_xinerama_screens(Rect **xin_areas, guint *nxin)
void screen_update_areas(void) void screen_update_areas(void)
{ {
guint i, j; guint j;
gulong *dims; gulong *dims;
GList *it; GList *it;
GSList *sit; GSList *sit;
@ -1377,7 +1364,7 @@ void screen_update_areas(void)
config_margins.right_start = RECT_TOP(monitor_area[screen_num_monitors]); config_margins.right_start = RECT_TOP(monitor_area[screen_num_monitors]);
config_margins.right_end = RECT_BOTTOM(monitor_area[screen_num_monitors]); config_margins.right_end = RECT_BOTTOM(monitor_area[screen_num_monitors]);
dims = g_new(gulong, 4 * screen_num_desktops * screen_num_monitors); dims = g_new(gulong, 4 * screen_num_desktops);
RESET_STRUT_LIST(struts_left); RESET_STRUT_LIST(struts_left);
RESET_STRUT_LIST(struts_top); RESET_STRUT_LIST(struts_top);
@ -1423,69 +1410,51 @@ void screen_update_areas(void)
VALIDATE_STRUTS(struts_bottom, bottom, VALIDATE_STRUTS(struts_bottom, bottom,
monitor_area[screen_num_monitors].height / 2); monitor_area[screen_num_monitors].height / 2);
/* set up the work areas to be full screen */ /* set up the work area to be full screen across all monitors */
for (i = 0; i < screen_num_monitors; ++i) for (j = 0; j < screen_num_desktops; ++j) {
for (j = 0; j < screen_num_desktops; ++j) { dims[j*4 + 0] =
dims[(i * screen_num_desktops + j) * 4+0] = monitor_area[i].x; monitor_area[screen_num_monitors].x;
dims[(i * screen_num_desktops + j) * 4+1] = monitor_area[i].y; dims[j*4 + 1] =
dims[(i * screen_num_desktops + j) * 4+2] = monitor_area[i].width; monitor_area[screen_num_monitors].y;
dims[(i * screen_num_desktops + j) * 4+3] = monitor_area[i].height; dims[j*4 + 2] =
monitor_area[screen_num_monitors].width;
dims[j*4 + 3] =
monitor_area[screen_num_monitors].height;
}
/* calculate the work area from the struts */
for (j = 0; j < screen_num_desktops; ++j) {
gint l = 0, r = 0, t = 0, b = 0;
for (sit = struts_left; sit; sit = g_slist_next(sit)) {
ObScreenStrut *s = sit->data;
if (s->desktop == j || s->desktop == DESKTOP_ALL)
l = MAX(l, s->strut->left);
}
for (sit = struts_top; sit; sit = g_slist_next(sit)) {
ObScreenStrut *s = sit->data;
if (s->desktop == j || s->desktop == DESKTOP_ALL)
t = MAX(t, s->strut->top);
}
for (sit = struts_right; sit; sit = g_slist_next(sit)) {
ObScreenStrut *s = sit->data;
if (s->desktop == j || s->desktop == DESKTOP_ALL)
r = MAX(r, s->strut->right);
}
for (sit = struts_bottom; sit; sit = g_slist_next(sit)) {
ObScreenStrut *s = sit->data;
if (s->desktop == j || s->desktop == DESKTOP_ALL)
b = MAX(b, s->strut->bottom);
} }
/* calculate the work areas from the struts */ /* based on these margins, set the work area for the desktop */
for (i = 0; i < screen_num_monitors; ++i) dims[j*4 + 0] += l;
for (j = 0; j < screen_num_desktops; ++j) { dims[j*4 + 1] += t;
gint l = 0, r = 0, t = 0, b = 0; dims[j*4 + 2] -= l + r;
dims[j*4 + 3] -= t + b;
}
/* only add the strut to the area if it touches the monitor */ /* set the legacy workarea hint to the union of all the monitors */
for (sit = struts_left; sit; sit = g_slist_next(sit)) {
ObScreenStrut *s = sit->data;
if ((s->desktop == j || s->desktop == DESKTOP_ALL) &&
STRUT_LEFT_ON_MONITOR(s->strut, i))
l = MAX(l, s->strut->left);
}
for (sit = struts_top; sit; sit = g_slist_next(sit)) {
ObScreenStrut *s = sit->data;
if ((s->desktop == j || s->desktop == DESKTOP_ALL) &&
STRUT_TOP_ON_MONITOR(s->strut, i))
t = MAX(t, s->strut->top);
}
for (sit = struts_right; sit; sit = g_slist_next(sit)) {
ObScreenStrut *s = sit->data;
if ((s->desktop == j || s->desktop == DESKTOP_ALL) &&
STRUT_RIGHT_ON_MONITOR(s->strut, i))
r = MAX(r, s->strut->right);
}
for (sit = struts_bottom; sit; sit = g_slist_next(sit)) {
ObScreenStrut *s = sit->data;
if ((s->desktop == j || s->desktop == DESKTOP_ALL) &&
STRUT_BOTTOM_ON_MONITOR(s->strut, i))
b = MAX(b, s->strut->bottom);
}
/* if the monitor is not against the edge of the root window,
the struts will include the distance from the root window's edge
to the monitor, so add that back into the monitor's work area */
if (l) l += RECT_LEFT (monitor_area[screen_num_monitors])
- RECT_LEFT (monitor_area[i]);
if (t) t += RECT_TOP (monitor_area[screen_num_monitors])
- RECT_TOP (monitor_area[i]);
if (r) r -= RECT_RIGHT (monitor_area[screen_num_monitors])
- RECT_RIGHT (monitor_area[i]);
if (b) b -= RECT_BOTTOM(monitor_area[screen_num_monitors])
- RECT_BOTTOM(monitor_area[i]);
/* based on these margins, set the work area for the
monitor/desktop */
dims[(i * screen_num_desktops + j) * 4 + 0] += l;
dims[(i * screen_num_desktops + j) * 4 + 1] += t;
dims[(i * screen_num_desktops + j) * 4 + 2] -= l + r;
dims[(i * screen_num_desktops + j) * 4 + 3] -= t + b;
}
/* all the work areas are not used here, only the ones for the first
monitor are */
OBT_PROP_SETA32(obt_root(ob_screen), NET_WORKAREA, CARDINAL, OBT_PROP_SETA32(obt_root(ob_screen), NET_WORKAREA, CARDINAL,
dims, 4 * screen_num_desktops); dims, 4 * screen_num_desktops);
@ -1724,7 +1693,7 @@ Rect* screen_physical_area_active(void)
return screen_physical_area_monitor(screen_monitor_active()); return screen_physical_area_monitor(screen_monitor_active());
} }
guint screen_monitor_primary(void) guint screen_monitor_primary(gboolean fixed)
{ {
if (config_primary_monitor_index > 0) { if (config_primary_monitor_index > 0) {
if (config_primary_monitor_index-1 < screen_num_monitors) if (config_primary_monitor_index-1 < screen_num_monitors)
@ -1732,15 +1701,17 @@ guint screen_monitor_primary(void)
else else
return 0; return 0;
} }
else if (fixed)
return 0;
else if (config_primary_monitor == OB_PLACE_MONITOR_ACTIVE) else if (config_primary_monitor == OB_PLACE_MONITOR_ACTIVE)
return screen_monitor_active(); return screen_monitor_active();
else /* config_primary_monitor == OB_PLACE_MONITOR_MOUSE */ else /* config_primary_monitor == OB_PLACE_MONITOR_MOUSE */
return screen_monitor_pointer(); return screen_monitor_pointer();
} }
Rect *screen_physical_area_primary(void) Rect *screen_physical_area_primary(gboolean fixed)
{ {
return screen_physical_area_monitor(screen_monitor_primary()); return screen_physical_area_monitor(screen_monitor_primary(fixed));
} }
void screen_set_root_cursor(void) void screen_set_root_cursor(void)
@ -1753,17 +1724,21 @@ void screen_set_root_cursor(void)
ob_cursor(OB_CURSOR_POINTER)); ob_cursor(OB_CURSOR_POINTER));
} }
guint screen_monitor_pointer() guint screen_find_monitor_point(guint x, guint y)
{ {
Rect mon; Rect mon;
gint x, y; RECT_SET(mon, x, y, 1, 1);
if (screen_pointer_pos(&x, &y))
RECT_SET(mon, x, y, 1, 1);
else
RECT_SET(mon, 0, 0, 1, 1);
return screen_find_monitor(&mon); return screen_find_monitor(&mon);
} }
guint screen_monitor_pointer()
{
gint x, y;
if (!screen_pointer_pos(&x, &y))
x = y = 0;
return screen_find_monitor_point(x, y);
}
gboolean screen_pointer_pos(gint *x, gint *y) gboolean screen_pointer_pos(gint *x, gint *y)
{ {
Window w; Window w;

View file

@ -110,10 +110,18 @@ guint screen_monitor_active(void);
Rect *screen_physical_area_active(void); Rect *screen_physical_area_active(void);
/*! Returns the primary monitor, as specified by the config */ /*! Returns the primary monitor, as specified by the config.
guint screen_monitor_primary(void); @fixed If TRUE, then this will always return a fixed monitor, otherwise
it may change based on where focus is, or other heuristics.
*/
guint screen_monitor_primary(gboolean fixed);
Rect *screen_physical_area_primary(void); /*! Returns physical area for the primary monitor, as specified by the config.
@fixed If TRUE, then this will always use a fixed monitor as primary,
otherwise it may change based on where focus is, or other heuristics.
See screen_monitor_primary().
*/
Rect *screen_physical_area_primary(gboolean fixed);
/* doesn't include struts which the search area is already outside of when /* doesn't include struts which the search area is already outside of when
'search' is not NULL */ 'search' is not NULL */
@ -134,6 +142,9 @@ gboolean screen_physical_area_monitor_contains(guint head, Rect *search);
*/ */
guint screen_find_monitor(Rect *search); guint screen_find_monitor(Rect *search);
/*! Finds the monitor which contains the point @x, @y */
guint screen_find_monitor_point(guint x, guint y);
/*! Sets the root cursor. This function decides which cursor to use, but you /*! Sets the root cursor. This function decides which cursor to use, but you
gotta call it to let it know it should change. */ gotta call it to let it know it should change. */
void screen_set_root_cursor(void); void screen_set_root_cursor(void);

View file

@ -73,12 +73,14 @@ static void AddPicture(RrImage *self, RrImagePic ***list, gint *len,
/* add the picture as a key to point to this image in the cache */ /* add the picture as a key to point to this image in the cache */
g_hash_table_insert(self->cache->table, (*list)[0], self); g_hash_table_insert(self->cache->table, (*list)[0], self);
/*
#ifdef DEBUG #ifdef DEBUG
g_debug("Adding %s picture to the cache:\n " g_debug("Adding %s picture to the cache:\n "
"Image 0x%lx, w %d h %d Hash %u", "Image 0x%lx, w %d h %d Hash %u",
(*list == self->original ? "ORIGINAL" : "RESIZED"), (*list == self->original ? "ORIGINAL" : "RESIZED"),
(gulong)self, pic->width, pic->height, RrImagePicHash(pic)); (gulong)self, pic->width, pic->height, RrImagePicHash(pic));
#endif #endif
*/
} }
/*! Remove a picture from an Image. This may remove it from the "originals" /*! Remove a picture from an Image. This may remove it from the "originals"
@ -88,6 +90,7 @@ static void RemovePicture(RrImage *self, RrImagePic ***list,
{ {
gint j; gint j;
/*
#ifdef DEBUG #ifdef DEBUG
g_debug("Removing %s picture from the cache:\n " g_debug("Removing %s picture from the cache:\n "
"Image 0x%lx, w %d h %d Hash %u", "Image 0x%lx, w %d h %d Hash %u",
@ -95,6 +98,7 @@ static void RemovePicture(RrImage *self, RrImagePic ***list,
(gulong)self, (*list)[i]->width, (*list)[i]->height, (gulong)self, (*list)[i]->width, (*list)[i]->height,
RrImagePicHash((*list)[i])); RrImagePicHash((*list)[i]));
#endif #endif
*/
/* remove the picture as a key in the cache */ /* remove the picture as a key in the cache */
g_hash_table_remove(self->cache->table, (*list)[i]); g_hash_table_remove(self->cache->table, (*list)[i]);
@ -329,10 +333,12 @@ void RrImageRef(RrImage *self)
void RrImageUnref(RrImage *self) void RrImageUnref(RrImage *self)
{ {
if (self && --self->ref == 0) { if (self && --self->ref == 0) {
/*
#ifdef DEBUG #ifdef DEBUG
g_debug("Refcount to 0, removing ALL pictures from the cache:\n " g_debug("Refcount to 0, removing ALL pictures from the cache:\n "
"Image 0x%lx", (gulong)self); "Image 0x%lx", (gulong)self);
#endif #endif
*/
while (self->n_original > 0) while (self->n_original > 0)
RemovePicture(self, &self->original, 0, &self->n_original); RemovePicture(self, &self->original, 0, &self->n_original);
while (self->n_resized > 0) while (self->n_resized > 0)
@ -352,10 +358,12 @@ void RrImageAddPicture(RrImage *self, RrPixel32 *data, gint w, gint h)
/* make sure we don't already have this size.. */ /* make sure we don't already have this size.. */
for (i = 0; i < self->n_original; ++i) for (i = 0; i < self->n_original; ++i)
if (self->original[i]->width == w && self->original[i]->height == h) { if (self->original[i]->width == w && self->original[i]->height == h) {
/*
#ifdef DEBUG #ifdef DEBUG
g_debug("Found duplicate ORIGINAL image:\n " g_debug("Found duplicate ORIGINAL image:\n "
"Image 0x%lx, w %d h %d", (gulong)self, w, h); "Image 0x%lx, w %d h %d", (gulong)self, w, h);
#endif #endif
*/
return; return;
} }