diff --git a/obt/keyboard.c b/obt/keyboard.c index 699fa8ba..264201a6 100644 --- a/obt/keyboard.c +++ b/obt/keyboard.c @@ -185,16 +185,24 @@ static void set_modkey_mask(guchar mask, KeySym sym) /* 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 */ for (i = min_keycode; i <= max_keycode; ++i) for (j = 0; j < keysyms_per_keycode; ++j) - if (sym == keymap[(i-min_keycode) * keysyms_per_keycode + j]) - return i; - return 0; + if (sym == keymap[(i-min_keycode) * keysyms_per_keycode + j]) { + ret = g_renew(KeyCode, ret, ++n); + ret[n-1] = i; + ret[n] = 0; + } + return ret; } gchar *obt_keyboard_keycode_to_string(guint keycode) diff --git a/obt/keyboard.h b/obt/keyboard.h index dd28cb86..4fb60186 100644 --- a/obt/keyboard.h +++ b/obt/keyboard.h @@ -54,9 +54,8 @@ guint obt_keyboard_only_modmasks(guint mask); right keys when there are both. */ guint obt_keyboard_modkey_to_modmask(ObtModkeysKey key); -/*! Convert a KeySym to a KeyCode, because the X function is terrible - says - valgrind. */ -KeyCode obt_keyboard_keysym_to_keycode(KeySym sym); +/*! Convert a KeySym to all the KeyCodes which generate it. */ +KeyCode* obt_keyboard_keysym_to_keycode(KeySym sym); /*! Give the string form of a KeyCode */ gchar *obt_keyboard_keycode_to_string(guint keycode); diff --git a/openbox/actions/cyclewindows.c b/openbox/actions/cyclewindows.c index 5354f087..6d847837 100644 --- a/openbox/actions/cyclewindows.c +++ b/openbox/actions/cyclewindows.c @@ -146,13 +146,13 @@ static gboolean i_input_func(guint initial_state, { if (e->type == KeyPress) { /* 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); return FALSE; } /* 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) { end_cycle(FALSE, e->xkey.state, options); diff --git a/openbox/actions/directionalwindows.c b/openbox/actions/directionalwindows.c index acd4f8a2..3d997aef 100644 --- a/openbox/actions/directionalwindows.c +++ b/openbox/actions/directionalwindows.c @@ -216,13 +216,13 @@ static gboolean i_input_func(guint initial_state, { if (e->type == KeyPress) { /* 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); return FALSE; } /* 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) { end_cycle(FALSE, e->xkey.state, options); diff --git a/openbox/event.c b/openbox/event.c index 04c6a7c6..1caa8acc 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -1751,30 +1751,30 @@ static gboolean event_handle_menu_input(XEvent *ev) else if (ev->type == KeyPress && (state & ~ControlMask) == 0) { frame->got_press = TRUE; - if (keycode == ob_keycode(OB_KEY_ESCAPE)) { + if (ob_keycode_match(keycode, OB_KEY_ESCAPE)) { menu_frame_hide_all(); 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 */ if (frame->parent) menu_frame_select(frame, NULL, 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 */ if (frame->child) menu_frame_select_next(frame->child); ret = TRUE; } - else if (keycode == ob_keycode(OB_KEY_UP)) { + else if (ob_keycode_match(keycode, OB_KEY_UP)) { menu_frame_select_previous(frame); ret = TRUE; } - else if (keycode == ob_keycode(OB_KEY_DOWN)) { + else if (ob_keycode_match(keycode, OB_KEY_DOWN)) { menu_frame_select_next(frame); ret = TRUE; } @@ -1787,7 +1787,7 @@ static gboolean event_handle_menu_input(XEvent *ev) else if (ev->type == KeyRelease && (state & ~ControlMask) == 0 && 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. Control-Enter runs it without closing the menu. */ if (frame->child) @@ -1885,7 +1885,12 @@ static void event_handle_menu(ObMenuFrame *frame, XEvent *ev) (f = find_active_menu()) && f->selected == e && 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; } diff --git a/openbox/focus_cycle_popup.c b/openbox/focus_cycle_popup.c index 2ad786c0..d6d5584c 100644 --- a/openbox/focus_cycle_popup.c +++ b/openbox/focus_cycle_popup.c @@ -351,7 +351,7 @@ static void popup_render(ObFocusCyclePopup *p, const ObClient *c) g_assert(mode == OB_FOCUS_CYCLE_POPUP_MODE_ICONS || mode == OB_FOCUS_CYCLE_POPUP_MODE_LIST); - screen_area = screen_physical_area_primary(); + screen_area = screen_physical_area_primary(FALSE); /* get the outside margins */ 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); /* position the popup */ - a = screen_physical_area_primary(); + a = screen_physical_area_primary(FALSE); icon_popup_position(single_popup, CenterGravity, a->x + a->width / 2, a->y + a->height / 2); icon_popup_height(single_popup, POPUP_HEIGHT); diff --git a/openbox/keyboard.c b/openbox/keyboard.c index ade18d04..a342d1ef 100644 --- a/openbox/keyboard.c +++ b/openbox/keyboard.c @@ -89,7 +89,7 @@ static void set_curpos(KeyBindingTree *newpos) g_free(oldtext); } - a = screen_physical_area_primary(); + a = screen_physical_area_primary(FALSE); popup_position(popup, NorthWestGravity, a->x + 10, a->y + 10); /* 1 second delay for the popup to show */ popup_delay_show(popup, G_USEC_PER_SEC, text); diff --git a/openbox/menuframe.c b/openbox/menuframe.c index 1dbc6d4e..999dddf1 100644 --- a/openbox/menuframe.c +++ b/openbox/menuframe.c @@ -22,6 +22,7 @@ #include "menu.h" #include "screen.h" #include "actions.h" +#include "event.h" #include "grab.h" #include "openbox.h" #include "config.h" @@ -47,7 +48,8 @@ static ObMenuEntryFrame* menu_entry_frame_new(ObMenuEntry *entry, ObMenuFrame *frame); static void menu_entry_frame_free(ObMenuEntryFrame *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 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->menu = menu; self->selected = NULL; + self->open_submenu = NULL; self->client = client; self->direction_right = TRUE; 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) { 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); } @@ -299,7 +303,7 @@ void menu_frame_move_on_screen(ObMenuFrame *self, gint x, gint y, *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; 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) { gint px, py; - guint i; if (menu_frame_is_visible(self)) return TRUE; if (!menu_frame_show(self)) 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) self->menu->place_func(self, &x, &y, mouse, self->menu->data); else @@ -1005,6 +997,7 @@ gboolean menu_frame_show_submenu(ObMenuFrame *self, ObMenuFrame *parent, self->monitor = parent->monitor; self->parent = parent; self->parent_entry = parent_entry; + parent->open_submenu = parent_entry; /* set up parent's child to be us */ if (parent->child) @@ -1039,6 +1032,7 @@ gboolean menu_frame_show_submenu(ObMenuFrame *self, ObMenuFrame *parent, static void menu_frame_hide(ObMenuFrame *self) { GList *it = g_list_find(menu_frame_visible, self); + gulong ignore_start; if (!it) return; @@ -1049,8 +1043,10 @@ static void menu_frame_hide(ObMenuFrame *self) if (self->child) menu_frame_hide(self->child); - if (self->parent) + if (self->parent && self->parent->child == self) { self->parent->child = NULL; + self->parent->open_submenu = NULL; + } self->parent = NULL; self->parent_entry = NULL; @@ -1062,7 +1058,9 @@ static void menu_frame_hide(ObMenuFrame *self) ungrab_keyboard(); } + ignore_start = event_start_ignore_all_enters(); XUnmapWindow(obt_display, self->window); + event_end_ignore_all_enters(ignore_start); menu_frame_free(self); } @@ -1074,7 +1072,10 @@ void menu_frame_hide_all(void) if (config_submenu_show_delay) { /* remove any submenu open requests */ 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))) menu_frame_hide(it->data); @@ -1088,8 +1089,13 @@ void menu_frame_hide_all_client(ObClient *client) if (f->client == client) { if (config_submenu_show_delay) { /* remove any submenu open requests */ - obt_main_loop_timeout_remove(ob_main_loop, - menu_entry_frame_submenu_timeout); + obt_main_loop_timeout_remove + (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); } @@ -1124,7 +1130,6 @@ ObMenuEntryFrame* menu_entry_frame_under(gint x, gint y) for (it = frame->entries; it; it = g_list_next(it)) { ObMenuEntryFrame *e = it->data; - if (RECT_CONTAINS(e->area, x, y)) { ret = e; break; @@ -1134,7 +1139,15 @@ ObMenuEntryFrame* menu_entry_frame_under(gint x, gint y) 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); menu_entry_frame_show_submenu((ObMenuEntryFrame*)data); @@ -1155,27 +1168,67 @@ void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry, if (config_submenu_show_delay) { /* remove any submenu open requests */ 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; if (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) { 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) { /* initiate a new submenu open request */ - obt_main_loop_timeout_add(ob_main_loop, - config_submenu_show_delay * 1000, - menu_entry_frame_submenu_timeout, - self->selected, g_direct_equal, - NULL); + obt_main_loop_timeout_add + (ob_main_loop, + config_submenu_show_delay * 1000, + menu_entry_frame_submenu_show_timeout, + self->selected, g_direct_equal, + NULL); } else { menu_entry_frame_show_submenu(self->selected); } diff --git a/openbox/menuframe.h b/openbox/menuframe.h index 1d5dd0cb..f6a7b30e 100644 --- a/openbox/menuframe.h +++ b/openbox/menuframe.h @@ -53,6 +53,9 @@ struct _ObMenuFrame GList *entries; 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 */ guint show_from; diff --git a/openbox/moveresize.c b/openbox/moveresize.c index d89c31ca..5db79f9f 100644 --- a/openbox/moveresize.c +++ b/openbox/moveresize.c @@ -605,13 +605,13 @@ static void move_with_keys(gint keycode, gint state) gint x, y; ObDirection dir; - if (keycode == ob_keycode(OB_KEY_RIGHT)) + if (ob_keycode_match(keycode, OB_KEY_RIGHT)) 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; - else if (keycode == ob_keycode(OB_KEY_DOWN)) + else if (ob_keycode_match(keycode, OB_KEY_DOWN)) 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; client_find_move_directional(moveresize_client, dir, &x, &y); @@ -627,13 +627,13 @@ static void move_with_keys(gint keycode, gint state) else dist = KEY_DIST; - if (keycode == ob_keycode(OB_KEY_RIGHT)) + if (ob_keycode_match(keycode, OB_KEY_RIGHT)) dx = dist; - else if (keycode == ob_keycode(OB_KEY_LEFT)) + else if (ob_keycode_match(keycode, OB_KEY_LEFT)) dx = -dist; - else if (keycode == ob_keycode(OB_KEY_DOWN)) + else if (ob_keycode_match(keycode, OB_KEY_DOWN)) dy = dist; - else /* if (keycode == ob_keycode(OB_KEY_UP)) */ + else /* if (ob_keycode_match(keycode, OB_KEY_UP)) */ dy = -dist; } @@ -666,7 +666,7 @@ static void resize_with_keys(gint keycode, gint state) ObDirection dir; /* 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; if (key_resize_edge != OB_DIRECTION_WEST && 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; return; } - } else if (keycode == ob_keycode(OB_KEY_LEFT)) { + } else if (ob_keycode_match(keycode, OB_KEY_LEFT)) { dir = OB_DIRECTION_WEST; if (key_resize_edge != OB_DIRECTION_WEST && 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; return; } - } else if (keycode == ob_keycode(OB_KEY_UP)) { + } else if (ob_keycode_match(keycode, OB_KEY_UP)) { dir = OB_DIRECTION_NORTH; if (key_resize_edge != OB_DIRECTION_NORTH && 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; return; } - } else /* if (keycode == ob_keycode(OB_KEY_DOWN)) */ { + } else /* if (ob_keycode_match(keycode, OB_KEY_DOWN)) */ { dir = OB_DIRECTION_SOUTH; if (key_resize_edge != OB_DIRECTION_NORTH && 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)) { gint x, y, w, h; - if (keycode == ob_keycode(OB_KEY_RIGHT)) + if (ob_keycode_match(keycode, OB_KEY_RIGHT)) 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; - else if (keycode == ob_keycode(OB_KEY_DOWN)) + else if (ob_keycode_match(keycode, OB_KEY_DOWN)) 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; client_find_resize_directional(moveresize_client, key_resize_edge, @@ -912,16 +912,16 @@ gboolean moveresize_event(XEvent *e) } used = TRUE; } 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); 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); used = TRUE; - } else if (e->xkey.keycode == ob_keycode(OB_KEY_RIGHT) || - e->xkey.keycode == ob_keycode(OB_KEY_LEFT) || - e->xkey.keycode == ob_keycode(OB_KEY_DOWN) || - e->xkey.keycode == ob_keycode(OB_KEY_UP)) + } else if (ob_keycode_match(e->xkey.keycode, OB_KEY_RIGHT) || + ob_keycode_match(e->xkey.keycode, OB_KEY_LEFT) || + ob_keycode_match(e->xkey.keycode, OB_KEY_DOWN) || + ob_keycode_match(e->xkey.keycode, OB_KEY_UP)) { if (corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_KEYBOARD)) { resize_with_keys(e->xkey.keycode, e->xkey.state); diff --git a/openbox/openbox.c b/openbox/openbox.c index 29506c00..800e6a21 100644 --- a/openbox/openbox.c +++ b/openbox/openbox.c @@ -101,7 +101,7 @@ static gboolean reconfigure = FALSE; static gboolean restart = FALSE; static gchar *restart_path = NULL; static Cursor cursors[OB_NUM_CURSORS]; -static KeyCode keys[OB_NUM_KEYS]; +static KeyCode *keys[OB_NUM_KEYS]; static gint exitcode = 0; static guint remote_control = 0; static gboolean being_replaced = FALSE; @@ -400,6 +400,16 @@ gint main(gint argc, gchar **argv) event_shutdown(reconfigure); config_shutdown(); 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); } @@ -716,10 +726,14 @@ Cursor ob_cursor(ObCursor 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); - return keys[key]; + for (k = keys[key]; *k; ++k) + if (*k == code) return TRUE; + return FALSE; } ObState ob_state(void) diff --git a/openbox/openbox.h b/openbox/openbox.h index b2e9c4cb..b0529219 100644 --- a/openbox/openbox.h +++ b/openbox/openbox.h @@ -62,6 +62,6 @@ void ob_exit_with_error(const gchar *msg) G_GNUC_NORETURN; Cursor ob_cursor(ObCursor cursor); -KeyCode ob_keycode(ObKey key); +gboolean ob_keycode_match(KeyCode code, ObKey key); #endif diff --git a/openbox/prompt.c b/openbox/prompt.c index 51511005..785a864d 100644 --- a/openbox/prompt.c +++ b/openbox/prompt.c @@ -531,23 +531,23 @@ gboolean prompt_key_event(ObPrompt *self, XEvent *e) if (e->xkey.state != 0 && e->xkey.state != shift_mask) return FALSE; - if (e->xkey.keycode == ob_keycode(OB_KEY_ESCAPE)) + if (ob_keycode_match(e->xkey.keycode, OB_KEY_ESCAPE)) prompt_cancel(self); - else if (e->xkey.keycode == ob_keycode(OB_KEY_RETURN) || - e->xkey.keycode == ob_keycode(OB_KEY_SPACE)) + else if (ob_keycode_match(e->xkey.keycode, OB_KEY_RETURN) || + ob_keycode_match(e->xkey.keycode, OB_KEY_SPACE)) { prompt_run_callback(self, self->focus->result); } - else if (e->xkey.keycode == ob_keycode(OB_KEY_TAB) || - e->xkey.keycode == ob_keycode(OB_KEY_LEFT) || - e->xkey.keycode == ob_keycode(OB_KEY_RIGHT)) + else if (ob_keycode_match(e->xkey.keycode, OB_KEY_TAB) || + ob_keycode_match(e->xkey.keycode, OB_KEY_LEFT) || + ob_keycode_match(e->xkey.keycode, OB_KEY_RIGHT)) { gint i; gboolean left; ObPromptElement *oldfocus; - left = e->xkey.keycode == ob_keycode(OB_KEY_LEFT) || - (e->xkey.keycode == ob_keycode(OB_KEY_TAB) && shift); + left = ob_keycode_match(e->xkey.keycode, OB_KEY_LEFT) || + (ob_keycode_match(e->xkey.keycode, OB_KEY_TAB) && shift); oldfocus = self->focus; for (i = 0; i < self->n_buttons; ++i) diff --git a/openbox/screen.c b/openbox/screen.c index 8012942b..5050a685 100644 --- a/openbox/screen.c +++ b/openbox/screen.c @@ -929,7 +929,7 @@ void screen_show_desktop_popup(guint d) /* 0 means don't show the popup */ if (!config_desktop_popup_time) return; - a = screen_physical_area_primary(); + a = screen_physical_area_primary(FALSE); pager_popup_position(desktop_popup, CenterGravity, a->x + a->width / 2, a->y + a->height / 2); 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 { guint desktop; StrutPartial *strut; @@ -1359,7 +1346,7 @@ static void get_xinerama_screens(Rect **xin_areas, guint *nxin) void screen_update_areas(void) { - guint i, j; + guint j; gulong *dims; GList *it; 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_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_top); @@ -1423,69 +1410,51 @@ void screen_update_areas(void) VALIDATE_STRUTS(struts_bottom, bottom, monitor_area[screen_num_monitors].height / 2); - /* set up the work areas to be full screen */ - for (i = 0; i < screen_num_monitors; ++i) - for (j = 0; j < screen_num_desktops; ++j) { - dims[(i * screen_num_desktops + j) * 4+0] = monitor_area[i].x; - dims[(i * screen_num_desktops + j) * 4+1] = monitor_area[i].y; - dims[(i * screen_num_desktops + j) * 4+2] = monitor_area[i].width; - dims[(i * screen_num_desktops + j) * 4+3] = monitor_area[i].height; + /* set up the work area to be full screen across all monitors */ + for (j = 0; j < screen_num_desktops; ++j) { + dims[j*4 + 0] = + monitor_area[screen_num_monitors].x; + dims[j*4 + 1] = + monitor_area[screen_num_monitors].y; + 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 */ - for (i = 0; i < screen_num_monitors; ++i) - for (j = 0; j < screen_num_desktops; ++j) { - gint l = 0, r = 0, t = 0, b = 0; + /* based on these margins, set the work area for the desktop */ + dims[j*4 + 0] += l; + dims[j*4 + 1] += t; + dims[j*4 + 2] -= l + r; + dims[j*4 + 3] -= t + b; + } - /* only add the strut to the area if it touches the monitor */ - - 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 */ + /* set the legacy workarea hint to the union of all the monitors */ OBT_PROP_SETA32(obt_root(ob_screen), NET_WORKAREA, CARDINAL, dims, 4 * screen_num_desktops); @@ -1724,7 +1693,7 @@ Rect* screen_physical_area_active(void) 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-1 < screen_num_monitors) @@ -1732,15 +1701,17 @@ guint screen_monitor_primary(void) else return 0; } + else if (fixed) + return 0; else if (config_primary_monitor == OB_PLACE_MONITOR_ACTIVE) return screen_monitor_active(); else /* config_primary_monitor == OB_PLACE_MONITOR_MOUSE */ 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) @@ -1753,17 +1724,21 @@ void screen_set_root_cursor(void) ob_cursor(OB_CURSOR_POINTER)); } -guint screen_monitor_pointer() +guint screen_find_monitor_point(guint x, guint y) { Rect mon; - gint x, y; - if (screen_pointer_pos(&x, &y)) - RECT_SET(mon, x, y, 1, 1); - else - RECT_SET(mon, 0, 0, 1, 1); + RECT_SET(mon, x, y, 1, 1); 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) { Window w; diff --git a/openbox/screen.h b/openbox/screen.h index 1479db16..750de946 100644 --- a/openbox/screen.h +++ b/openbox/screen.h @@ -110,10 +110,18 @@ guint screen_monitor_active(void); Rect *screen_physical_area_active(void); -/*! Returns the primary monitor, as specified by the config */ -guint screen_monitor_primary(void); +/*! Returns the primary monitor, as specified by the config. + @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 'search' is not NULL */ @@ -134,6 +142,9 @@ gboolean screen_physical_area_monitor_contains(guint head, 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 gotta call it to let it know it should change. */ void screen_set_root_cursor(void); diff --git a/render/image.c b/render/image.c index 79f47fe2..924504fd 100644 --- a/render/image.c +++ b/render/image.c @@ -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 */ g_hash_table_insert(self->cache->table, (*list)[0], self); +/* #ifdef DEBUG g_debug("Adding %s picture to the cache:\n " "Image 0x%lx, w %d h %d Hash %u", (*list == self->original ? "ORIGINAL" : "RESIZED"), (gulong)self, pic->width, pic->height, RrImagePicHash(pic)); #endif +*/ } /*! 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; +/* #ifdef DEBUG g_debug("Removing %s picture from the cache:\n " "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, RrImagePicHash((*list)[i])); #endif +*/ /* remove the picture as a key in the cache */ g_hash_table_remove(self->cache->table, (*list)[i]); @@ -329,10 +333,12 @@ void RrImageRef(RrImage *self) void RrImageUnref(RrImage *self) { if (self && --self->ref == 0) { +/* #ifdef DEBUG g_debug("Refcount to 0, removing ALL pictures from the cache:\n " "Image 0x%lx", (gulong)self); #endif +*/ while (self->n_original > 0) RemovePicture(self, &self->original, 0, &self->n_original); 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.. */ for (i = 0; i < self->n_original; ++i) if (self->original[i]->width == w && self->original[i]->height == h) { +/* #ifdef DEBUG g_debug("Found duplicate ORIGINAL image:\n " "Image 0x%lx, w %d h %d", (gulong)self, w, h); #endif +*/ return; }