From b77c4f812a513e3172b43eca1b9750fc2f911dfc Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Wed, 9 May 2007 18:04:16 +0000 Subject: [PATCH] merge r6183-6221 from trunk --- Makefile.am | 2 + data/rc.xml.in | 1 - data/rc.xsd | 1 - openbox/action.c | 33 +-- openbox/client.c | 124 ++++++--- openbox/client.h | 35 ++- openbox/client_list_combined_menu.c | 3 +- openbox/client_list_menu.c | 3 +- openbox/client_menu.c | 281 +++++++++++-------- openbox/config.c | 11 +- openbox/config.h | 2 - openbox/event.c | 38 +-- openbox/frame.c | 296 ++++++++++---------- openbox/frame.h | 12 +- openbox/framerender.c | 14 +- openbox/group.c | 10 +- openbox/group.h | 2 - openbox/keyboard.c | 10 +- openbox/menu.h | 2 + openbox/menuframe.c | 10 +- openbox/menuframe.h | 2 + openbox/moveresize.c | 58 ++-- openbox/moveresize.h | 1 + openbox/openbox.c | 3 + openbox/place.c | 2 +- openbox/prop.c | 1 + openbox/prop.h | 1 + openbox/resist.c | 411 ++++++++++++++-------------- openbox/resist.h | 10 +- openbox/screen.c | 48 ++-- openbox/screen.h | 2 + openbox/window.c | 6 +- 32 files changed, 796 insertions(+), 639 deletions(-) diff --git a/Makefile.am b/Makefile.am index 9269fb50..84bf7523 100644 --- a/Makefile.am +++ b/Makefile.am @@ -201,6 +201,8 @@ openbox_openbox_SOURCES = \ openbox/popup.h \ openbox/prop.c \ openbox/prop.h \ + openbox/propwin.c \ + openbox/propwin.h \ openbox/resist.c \ openbox/resist.h \ openbox/screen.c \ diff --git a/data/rc.xml.in b/data/rc.xml.in index 35cc4cfb..8ccf1cfa 100644 --- a/data/rc.xml.in +++ b/data/rc.xml.in @@ -42,7 +42,6 @@ D: omnipresent (on all desktops). --> yes - no yes sans diff --git a/data/rc.xsd b/data/rc.xsd index d3df567d..af4eda4a 100644 --- a/data/rc.xsd +++ b/data/rc.xsd @@ -111,7 +111,6 @@ - diff --git a/openbox/action.c b/openbox/action.c index f8b2b7b3..24388dca 100644 --- a/openbox/action.c +++ b/openbox/action.c @@ -1199,10 +1199,9 @@ void action_execute(union ActionData *data) void action_activate(union ActionData *data) { if (data->client.any.c) { - /* similar to the openbox dock for dockapps, don't let user actions - give focus to 3rd-party docks (panels) either (unless they ask for - it themselves). */ - if (data->client.any.c->type != OB_CLIENT_TYPE_DOCK) { + if (!data->any.button || client_mouse_focusable(data->client.any.c) || + data->any.context != OB_FRAME_CONTEXT_CLIENT) + { /* if using focus_delay, stop the timer now so that focus doesn't go moving on us */ event_halt_focus_delay(); @@ -1220,10 +1219,9 @@ void action_activate(union ActionData *data) void action_focus(union ActionData *data) { if (data->client.any.c) { - /* similar to the openbox dock for dockapps, don't let user actions - give focus to 3rd-party docks (panels) either (unless they ask for - it themselves). */ - if (data->client.any.c->type != OB_CLIENT_TYPE_DOCK) { + if (!data->any.button || client_mouse_focusable(data->client.any.c) || + data->any.context != OB_FRAME_CONTEXT_CLIENT) + { /* if using focus_delay, stop the timer now so that focus doesn't go moving on us */ event_halt_focus_delay(); @@ -1523,11 +1521,6 @@ void action_send_to_desktop(union ActionData *data) void action_desktop(union ActionData *data) { - static guint first = (unsigned) -1; - - if (data->inter.any.interactive && first == (unsigned) -1) - first = screen_desktop; - if (!data->inter.any.interactive || (!data->inter.cancel && !data->inter.final)) { @@ -1538,14 +1531,8 @@ void action_desktop(union ActionData *data) if (data->inter.any.interactive) screen_desktop_popup(data->desktop.desk, TRUE); } - } else if (data->inter.cancel) { - screen_set_desktop(first, TRUE); - } - - if (!data->inter.any.interactive || data->inter.final) { + } else screen_desktop_popup(0, FALSE); - first = (unsigned) -1; - } } void action_desktop_dir(union ActionData *data) @@ -1562,7 +1549,7 @@ void action_desktop_dir(union ActionData *data) !data->sendtodir.inter.final || data->sendtodir.inter.cancel) { - screen_set_desktop(d, TRUE); + if (d != screen_desktop) screen_set_desktop(d, TRUE); } } @@ -1583,7 +1570,7 @@ void action_send_to_desktop_dir(union ActionData *data) data->sendtodir.inter.cancel) { client_set_desktop(c, d, data->sendtodir.follow); - if (data->sendtodir.follow) + if (data->sendtodir.follow && d != screen_desktop) screen_set_desktop(d, TRUE); } } @@ -1702,8 +1689,6 @@ void action_moveresize(union ActionData *data) ObClient *c = data->moveresize.any.c; guint32 corner; - if (!client_normal(c)) return; - if (data->moveresize.keyboard) { corner = (data->moveresize.move ? prop_atoms.net_wm_moveresize_move_keyboard : diff --git a/openbox/client.c b/openbox/client.c index e2b2636b..3f3f161d 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -32,6 +32,7 @@ #include "event.h" #include "grab.h" #include "focus.h" +#include "propwin.h" #include "stacking.h" #include "openbox.h" #include "group.h" @@ -64,7 +65,6 @@ typedef struct GList *client_list = NULL; static GSList *client_destructors = NULL; -static GSList *client_desktop_notifies = NULL; static void client_get_all(ObClient *self); static void client_toggle_border(ObClient *self, gboolean show); @@ -104,6 +104,7 @@ void client_startup(gboolean reconfig) void client_shutdown(gboolean reconfig) { + if (reconfig) return; } void client_add_destructor(ObClientCallback func, gpointer data) @@ -128,29 +129,6 @@ void client_remove_destructor(ObClientCallback func) } } -void client_add_desktop_notify(ObClientCallback func, gpointer data) -{ - ClientCallback *d = g_new(ClientCallback, 1); - d->func = func; - d->data = data; - client_desktop_notifies = g_slist_prepend(client_desktop_notifies, d); -} - -void client_remove_desktop_notify(ObClientCallback func) -{ - GSList *it; - - for (it = client_desktop_notifies; it; it = g_slist_next(it)) { - ClientCallback *d = it->data; - if (d->func == func) { - g_free(d); - client_desktop_notifies = - g_slist_delete_link(client_desktop_notifies, it); - break; - } - } -} - void client_set_list() { Window *windows, *win_it; @@ -540,6 +518,9 @@ void client_unmanage(ObClient *self) /* remove the window from our save set */ XChangeSaveSet(ob_display, self->window, SetModeDelete); + /* kill the property windows */ + propwin_remove(self->user_time_window, OB_PROPWIN_USER_TIME, self); + /* update the focus lists */ focus_order_remove(self); if (client_focused(self)) { @@ -1026,7 +1007,9 @@ static void client_get_all(ObClient *self) client_update_title(self); client_update_strut(self); client_update_icons(self); - client_update_user_time(self); + client_update_user_time_window(self); + if (!self->user_time_window) /* check if this would have been called */ + client_update_user_time(self); client_update_icon_geometry(self); } @@ -1599,10 +1582,15 @@ void client_setup_decor_and_functions(ObClient *self) self->functions &= ~(OB_CLIENT_FUNC_ICONIFY | OB_CLIENT_FUNC_RESIZE); break; + case OB_CLIENT_TYPE_SPLASH: + /* these don't get get any decorations, and the only thing you can + do with them is move them */ + self->decorations = 0; + self->functions = OB_CLIENT_FUNC_MOVE; + case OB_CLIENT_TYPE_DESKTOP: case OB_CLIENT_TYPE_DOCK: - case OB_CLIENT_TYPE_SPLASH: - /* none of these windows are manipulated by the window manager */ + /* these windows are not manipulated by the window manager */ self->decorations = 0; self->functions = 0; break; @@ -2038,8 +2026,15 @@ void client_update_icons(ObClient *self) void client_update_user_time(ObClient *self) { guint32 time; + gboolean got = FALSE; + + if (self->user_time_window) + got = PROP_GET32(self->user_time_window, + net_wm_user_time, cardinal, &time); + if (!got) + got = PROP_GET32(self->window, net_wm_user_time, cardinal, &time); - if (PROP_GET32(self->window, net_wm_user_time, cardinal, &time)) { + if (got) { /* we set this every time, not just when it grows, because in practice sometimes time goes backwards! (ntpdate.. yay....) so.. if it goes backward we don't want all windows to stop focusing. we'll just @@ -2048,9 +2043,39 @@ void client_update_user_time(ObClient *self) */ self->user_time = time; - /* - ob_debug("window %s user time %u\n", self->title, time); - */ + /*ob_debug("window %s user time %u\n", self->title, time);*/ + } +} + +void client_update_user_time_window(ObClient *self) +{ + guint32 w; + + if (!PROP_GET32(self->window, net_wm_user_time_window, window, &w)) + w = None; + + if (w != self->user_time_window) { + /* remove the old window */ + propwin_remove(self->user_time_window, OB_PROPWIN_USER_TIME, self); + self->user_time_window = None; + + if (self->group && self->group->leader == w) { + ob_debug_type(OB_DEBUG_APP_BUGS, "Window is setting its " + "_NET_WM_USER_TYPE_WINDOW to its group leader\n"); + /* do it anyways..? */ + } + else if (w == self->window) { + ob_debug_type(OB_DEBUG_APP_BUGS, "Window is setting its " + "_NET_WM_USER_TIME_WINDOW to itself\n"); + w = None; /* don't do it */ + } + + /* add the new window */ + propwin_add(w, OB_PROPWIN_USER_TIME, self); + self->user_time_window = w; + + /* and update from it */ + client_update_user_time(self); } } @@ -2394,6 +2419,22 @@ gboolean client_helper(ObClient *self) self->type == OB_CLIENT_TYPE_TOOLBAR); } +gboolean client_mouse_focusable(ObClient *self) +{ + return !(self->type == OB_CLIENT_TYPE_MENU || + self->type == OB_CLIENT_TYPE_TOOLBAR || + self->type == OB_CLIENT_TYPE_SPLASH || + self->type == OB_CLIENT_TYPE_DOCK); +} + +gboolean client_enter_focusable(ObClient *self) +{ + /* you can focus desktops but it shouldn't on enter */ + return (client_mouse_focusable(self) && + self->type != OB_CLIENT_TYPE_DESKTOP); +} + + static void client_apply_startup_state(ObClient *self, gint x, gint y) { gboolean pos = FALSE; /* has the window's position been configured? */ @@ -2446,7 +2487,7 @@ static void client_apply_startup_state(ObClient *self, gint x, gint y) pos = TRUE; } - /* if the client didn't get positioned yet, then do so now + /* if the client didn't get positioned yet, then do so now. call client_move even if the window is not being moved anywhere, because when we reparent it and decorate it, it is getting moved and we need to be telling it so with a ConfigureNotify event. @@ -2798,7 +2839,9 @@ static void client_iconify_recursive(ObClient *self, self->window); if (iconic) { - if (self->functions & OB_CLIENT_FUNC_ICONIFY) { + /* don't let non-normal windows iconify along with their parents + or whatever */ + if (client_normal(self)) { self->iconic = iconic; /* update the focus lists.. iconic windows go to the bottom of @@ -2841,9 +2884,11 @@ static void client_iconify_recursive(ObClient *self, void client_iconify(ObClient *self, gboolean iconic, gboolean curdesk) { - /* move up the transient chain as far as possible first */ - self = client_search_top_normal_parent(self); - client_iconify_recursive(self, iconic, curdesk); + if (self->functions & OB_CLIENT_FUNC_ICONIFY || !iconic) { + /* move up the transient chain as far as possible first */ + self = client_search_top_normal_parent(self); + client_iconify_recursive(self, iconic, curdesk); + } } void client_maximize(ObClient *self, gboolean max, gint dir) @@ -3018,13 +3063,6 @@ void client_set_desktop_recursive(ObClient *self, client_raise(self); if (STRUT_EXISTS(self->strut)) screen_update_areas(); - - /* call the notifies */ - GSList *it; - for (it = client_desktop_notifies; it; it = g_slist_next(it)) { - ClientCallback *d = it->data; - d->func(self, d->data); - } } /* move all transients */ diff --git a/openbox/client.h b/openbox/client.h index 5fb26262..f9a19483 100644 --- a/openbox/client.h +++ b/openbox/client.h @@ -289,13 +289,17 @@ struct _ObClient /*! The number of icons in icons */ guint nicons; - /* Where the window should iconify to/from */ + /*! Where the window should iconify to/from */ Rect icon_geometry; + /*! The time when the client last received user interaction */ guint32 user_time; + /*! A separate window for the client to update it's user_time on */ + Window user_time_window; }; -extern GList *client_list; +extern GList *client_list; +extern GHashTable *client_user_time_window_map; void client_startup(gboolean reconfig); void client_shutdown(gboolean reconfig); @@ -308,10 +312,6 @@ typedef void (*ObClientCallback)(ObClient *client, gpointer data); void client_add_destructor(ObClientCallback func, gpointer data); void client_remove_destructor(ObClientCallback func); -/*! Get notified when the client changes desktop */ -void client_add_desktop_notify(ObClientCallback func, gpointer data); -void client_remove_desktop_notify(ObClientCallback func); - /*! Manages all existing windows */ void client_manage_all(); /*! Manages a given window */ @@ -338,6 +338,17 @@ gboolean client_normal(ObClient *self); (utilty, menu, etc) */ gboolean client_helper(ObClient *self); +/*! Return if the client is a type which should be given focus from mouse + presses on the *client* window. This doesn't affect clicking on the + decorations. This doesn't count for focus cycling, different rules apply to + that. */ +gboolean client_mouse_focusable(ObClient *self); + +/*! Return if the client is a type which should be given focus from the + mouse entering the window. This doesn't count for focus cycling, different + rules apply to that. */ +gboolean client_enter_focusable(ObClient *self); + /* Returns if the window is focused */ gboolean client_focused(ObClient *self); @@ -453,6 +464,9 @@ void client_maximize(ObClient *self, gboolean max, gint dir); */ void client_shade(ObClient *self, gboolean shade); +/*! Set a client window to have decorations or not */ +void client_set_undecorated(ObClient *self, gboolean undecorated); + /*! Hilite the window to make the user notice it */ void client_hilite(ObClient *self, gboolean hilite); @@ -575,6 +589,8 @@ void client_update_strut(ObClient *self); void client_update_icons(ObClient *self); /*! Updates the window's user time */ void client_update_user_time(ObClient *self); +/*! Updates the window's user time window */ +void client_update_user_time_window(ObClient *self); /*! Updates the window's icon geometry (where to iconify to/from) */ void client_update_icon_geometry(ObClient *self); @@ -646,15 +662,12 @@ ObClient *client_search_transient(ObClient *self, ObClient *search); gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang); /*! Set a client window to be above/below other clients. - @layer < 0 indicates the client should be placed below other clients.
- = 0 indicates the client should be placed with other clients.
+ @layer < 0 indicates the client should be placed below other clients.
+ = 0 indicates the client should be placed with other clients.
> 0 indicates the client should be placed above other clients. */ void client_set_layer(ObClient *self, gint layer); -/*! Set a client window to have decorations or not */ -void client_set_undecorated(ObClient *self, gboolean undecorated); - guint client_monitor(ObClient *self); ObClient* client_under_pointer(); diff --git a/openbox/client_list_combined_menu.c b/openbox/client_list_combined_menu.c index fcc95f69..26430f35 100644 --- a/openbox/client_list_combined_menu.c +++ b/openbox/client_list_combined_menu.c @@ -109,7 +109,8 @@ static gboolean self_update(ObMenuFrame *frame, gpointer data) /* executes it using the client in the actions, since we set that when we make the actions! */ -static void menu_execute(ObMenuEntry *self, guint state, gpointer data, +static void menu_execute(ObMenuEntry *self, ObMenuFrame *f, + ObClient *c, guint state, gpointer data, Time time) { ObAction *a; diff --git a/openbox/client_list_menu.c b/openbox/client_list_menu.c index 12c16815..351790be 100644 --- a/openbox/client_list_menu.c +++ b/openbox/client_list_menu.c @@ -110,7 +110,8 @@ static gboolean desk_menu_update(ObMenuFrame *frame, gpointer data) /* executes it using the client in the actions, since we set that when we make the actions! */ -static void desk_menu_execute(ObMenuEntry *self, guint state, gpointer data, +static void desk_menu_execute(ObMenuEntry *self, ObMenuFrame *f, + ObClient *c, guint state, gpointer data, Time time) { ObAction *a; diff --git a/openbox/client_menu.c b/openbox/client_menu.c index 11e31965..a44fcbcc 100644 --- a/openbox/client_menu.c +++ b/openbox/client_menu.c @@ -23,6 +23,8 @@ #include "client.h" #include "openbox.h" #include "frame.h" +#include "moveresize.h" +#include "prop.h" #include "gettext.h" #include @@ -50,81 +52,177 @@ enum { CLIENT_CLOSE }; -static gboolean client_update(ObMenuFrame *frame, gpointer data) +static gboolean client_menu_update(ObMenuFrame *frame, gpointer data) { ObMenu *menu = frame->menu; - ObMenuEntry *e; GList *it; if (frame->client == NULL || !client_normal(frame->client)) return FALSE; /* don't show the menu */ for (it = menu->entries; it; it = g_list_next(it)) { - e = it->data; - if (e->type == OB_MENU_ENTRY_TYPE_NORMAL) - e->data.normal.enabled = TRUE; + ObMenuEntry *e = it->data; + gboolean *en = &e->data.normal.enabled; /* save some typing */ + ObClient *c = frame->client; + + if (e->type == OB_MENU_ENTRY_TYPE_NORMAL) { + switch (e->id) { + case CLIENT_ICONIFY: + *en = c->functions & OB_CLIENT_FUNC_ICONIFY; + break; + case CLIENT_RESTORE: + *en = c->max_horz || c->max_vert; + break; + case CLIENT_MAXIMIZE: + *en = ((c->functions & OB_CLIENT_FUNC_MAXIMIZE) && + (!c->max_horz || !c->max_vert)); + break; + case CLIENT_SHADE: + *en = c->functions & OB_CLIENT_FUNC_SHADE; + break; + case CLIENT_MOVE: + *en = c->functions & OB_CLIENT_FUNC_MOVE; + break; + case CLIENT_RESIZE: + *en = c->functions & OB_CLIENT_FUNC_RESIZE; + break; + case CLIENT_CLOSE: + *en = c->functions & OB_CLIENT_FUNC_CLOSE; + break; + case CLIENT_DECORATE: + *en = client_normal(c); + break; + default: + *en = TRUE; + } + } } + return TRUE; /* show the menu */ +} - e = menu_find_entry_id(menu, CLIENT_ICONIFY); - e->data.normal.enabled = frame->client->functions & OB_CLIENT_FUNC_ICONIFY; - - e = menu_find_entry_id(menu, CLIENT_RESTORE); - e->data.normal.enabled =frame->client->max_horz || frame->client->max_vert; - - e = menu_find_entry_id(menu, CLIENT_MAXIMIZE); - e->data.normal.enabled = - (frame->client->functions & OB_CLIENT_FUNC_MAXIMIZE) && - !frame->client->max_horz && !frame->client->max_vert; - - e = menu_find_entry_id(menu, CLIENT_SHADE); - e->data.normal.enabled = frame->client->functions & OB_CLIENT_FUNC_SHADE; - - e = menu_find_entry_id(menu, CLIENT_MOVE); - e->data.normal.enabled = frame->client->functions & OB_CLIENT_FUNC_MOVE; +static void client_menu_execute(ObMenuEntry *e, ObMenuFrame *f, + ObClient *c, guint state, gpointer data, + Time time) +{ + gint x, y; - e = menu_find_entry_id(menu, CLIENT_RESIZE); - e->data.normal.enabled = frame->client->functions & OB_CLIENT_FUNC_RESIZE; + g_assert(c); - e = menu_find_entry_id(menu, CLIENT_CLOSE); - e->data.normal.enabled = frame->client->functions & OB_CLIENT_FUNC_CLOSE; + switch (e->id) { + case CLIENT_ICONIFY: + /* the client won't be on screen anymore so hide the menu */ + menu_frame_hide_all(); + f = NULL; /* and don't update */ + + client_iconify(c, TRUE, FALSE); + break; + case CLIENT_RESTORE: + client_maximize(c, FALSE, 0); + break; + case CLIENT_MAXIMIZE: + client_maximize(c, TRUE, 0); + break; + case CLIENT_SHADE: + client_shade(c, !c->shaded); + break; + case CLIENT_DECORATE: + client_set_undecorated(c, !c->undecorated); + break; + case CLIENT_MOVE: + /* this needs to grab the keyboard so hide the menu */ + menu_frame_hide_all(); + f = NULL; /* and don't update */ + + screen_pointer_pos(&x, &y); + moveresize_start(c, x, y, 0, + prop_atoms.net_wm_moveresize_move_keyboard); + break; + case CLIENT_RESIZE: + /* this needs to grab the keyboard so hide the menu */ + menu_frame_hide_all(); + f = NULL; /* and don't update */ + + screen_pointer_pos(&x, &y); + moveresize_start(c, x, y, 0, + prop_atoms.net_wm_moveresize_size_keyboard); + break; + case CLIENT_CLOSE: + client_close(c); + break; + default: + g_assert_not_reached(); + } - e = menu_find_entry_id(menu, CLIENT_DECORATE); - e->data.normal.enabled = client_normal(frame->client); - return TRUE; /* show the menu */ + /* update the menu cuz stuff can have changed */ + if (f) { + client_menu_update(f, NULL); + menu_frame_render(f); + } } -static gboolean layer_update(ObMenuFrame *frame, gpointer data) +static gboolean layer_menu_update(ObMenuFrame *frame, gpointer data) { ObMenu *menu = frame->menu; - ObMenuEntry *e; GList *it; if (frame->client == NULL || !client_normal(frame->client)) return FALSE; /* don't show the menu */ for (it = menu->entries; it; it = g_list_next(it)) { - e = it->data; - if (e->type == OB_MENU_ENTRY_TYPE_NORMAL) - e->data.normal.enabled = TRUE; + ObMenuEntry *e = it->data; + gboolean *en = &e->data.normal.enabled; /* save some typing */ + ObClient *c = frame->client; + + if (e->type == OB_MENU_ENTRY_TYPE_NORMAL) { + switch (e->id) { + case LAYER_TOP: + *en = !c->above; + break; + case LAYER_NORMAL: + *en = c->above || c->below; + break; + case LAYER_BOTTOM: + *en = !c->below; + break; + default: + *en = TRUE; + } + } } + return TRUE; /* show the menu */ +} - e = menu_find_entry_id(menu, LAYER_TOP); - e->data.normal.enabled = !frame->client->above; - - e = menu_find_entry_id(menu, LAYER_NORMAL); - e->data.normal.enabled = (frame->client->above || frame->client->below); +static void layer_menu_execute(ObMenuEntry *e, ObMenuFrame *f, + ObClient *c, guint state, gpointer data, + Time time) +{ + g_assert(c); + + switch (e->id) { + case LAYER_TOP: + client_set_layer(c, 1); + break; + case LAYER_NORMAL: + client_set_layer(c, 0); + break; + case LAYER_BOTTOM: + client_set_layer(c, -1); + break; + default: + g_assert_not_reached(); + } - e = menu_find_entry_id(menu, LAYER_BOTTOM); - e->data.normal.enabled = !frame->client->below; - return TRUE; /* show the menu */ + /* update the menu cuz stuff can have changed */ + if (f) { + layer_menu_update(f, NULL); + menu_frame_render(f); + } } -static gboolean send_to_update(ObMenuFrame *frame, gpointer data) +static gboolean send_to_menu_update(ObMenuFrame *frame, gpointer data) { ObMenu *menu = frame->menu; guint i; - GSList *acts; - ObAction *act; ObMenuEntry *e; menu_clear_entries(menu); @@ -146,12 +244,8 @@ static gboolean send_to_update(ObMenuFrame *frame, gpointer data) name = screen_desktop_names[i]; } - act = action_from_string("SendToDesktop", - OB_USER_ACTION_MENU_SELECTION); - act->data.sendto.desk = desk; - act->data.sendto.follow = FALSE; - acts = g_slist_prepend(NULL, act); - e = menu_add_normal(menu, desk, name, acts, FALSE); + e = menu_add_normal(menu, desk, name, NULL, FALSE); + e->id = desk; if (desk == DESKTOP_ALL) { e->data.normal.mask = ob_rr_theme->desk_mask; e->data.normal.mask_normal_color = ob_rr_theme->menu_color; @@ -169,23 +263,16 @@ static gboolean send_to_update(ObMenuFrame *frame, gpointer data) return TRUE; /* show the menu */ } -static void desktop_change_callback(ObClient *c, gpointer data) +static void send_to_menu_execute(ObMenuEntry *e, ObMenuFrame *f, + ObClient *c, guint state, gpointer data, + Time time) { - ObMenuFrame *frame = data; - if (c == frame->client) { - /* the client won't even be on the screen anymore, so hide the menu */ - menu_frame_hide_all(); - } -} + g_assert(c); -static void show_callback(ObMenuFrame *frame, gpointer data) -{ - client_add_desktop_notify(desktop_change_callback, frame); -} - -static void hide_callback(ObMenuFrame *frame, gpointer data) -{ - client_remove_desktop_notify(desktop_change_callback); + client_set_desktop(c, e->id, FALSE); + /* the client won't even be on the screen anymore, so hide the menu */ + if (f) + menu_frame_hide_all(); } static void client_menu_place(ObMenuFrame *frame, gint *x, gint *y, @@ -253,44 +340,30 @@ static void client_menu_place(ObMenuFrame *frame, gint *x, gint *y, void client_menu_startup() { - GSList *acts; ObMenu *menu; ObMenuEntry *e; menu = menu_new(LAYER_MENU_NAME, _("&Layer"), TRUE, NULL); menu_show_all_shortcuts(menu, TRUE); - menu_set_update_func(menu, layer_update); - - acts = g_slist_prepend(NULL, action_from_string - ("SendToTopLayer", OB_USER_ACTION_MENU_SELECTION)); - menu_add_normal(menu, LAYER_TOP, _("Always on &top"), acts, TRUE); + menu_set_update_func(menu, layer_menu_update); + menu_set_execute_func(menu, layer_menu_execute); - acts = g_slist_prepend(NULL, action_from_string - ("SendToNormalLayer", - OB_USER_ACTION_MENU_SELECTION)); - menu_add_normal(menu, LAYER_NORMAL, _("&Normal"), acts, TRUE); - - acts = g_slist_prepend(NULL, action_from_string - ("SendToBottomLayer", - OB_USER_ACTION_MENU_SELECTION)); - menu_add_normal(menu, LAYER_BOTTOM, _("Always on &bottom"),acts, TRUE); + menu_add_normal(menu, LAYER_TOP, _("Always on &top"), NULL, TRUE); + menu_add_normal(menu, LAYER_NORMAL, _("&Normal"), NULL, TRUE); + menu_add_normal(menu, LAYER_BOTTOM, _("Always on &bottom"),NULL, TRUE); menu = menu_new(SEND_TO_MENU_NAME, _("&Send to desktop"), TRUE, NULL); - menu_set_update_func(menu, send_to_update); - menu_set_show_func(menu, show_callback); - menu_set_hide_func(menu, hide_callback); - + menu_set_update_func(menu, send_to_menu_update); + menu_set_execute_func(menu, send_to_menu_execute); menu = menu_new(CLIENT_MENU_NAME, _("Client menu"), TRUE, NULL); menu_show_all_shortcuts(menu, TRUE); - menu_set_update_func(menu, client_update); + menu_set_update_func(menu, client_menu_update); menu_set_place_func(menu, client_menu_place); + menu_set_execute_func(menu, client_menu_execute); - acts = g_slist_prepend(NULL, action_from_string - ("ToggleMaximizeFull", - OB_USER_ACTION_MENU_SELECTION)); - e = menu_add_normal(menu, CLIENT_RESTORE, _("R&estore"), acts, TRUE); + e = menu_add_normal(menu, CLIENT_RESTORE, _("R&estore"), NULL, TRUE); e->data.normal.mask = ob_rr_theme->max_toggled_mask; e->data.normal.mask_normal_color = ob_rr_theme->menu_color; e->data.normal.mask_selected_color = ob_rr_theme->menu_selected_color; @@ -298,17 +371,11 @@ void client_menu_startup() e->data.normal.mask_disabled_selected_color = ob_rr_theme->menu_disabled_selected_color; - acts = g_slist_prepend(NULL, action_from_string - ("Move", OB_USER_ACTION_MENU_SELECTION)); - menu_add_normal(menu, CLIENT_MOVE, _("&Move"), acts, TRUE); + menu_add_normal(menu, CLIENT_MOVE, _("&Move"), NULL, TRUE); - acts = g_slist_prepend(NULL, action_from_string - ("Resize", OB_USER_ACTION_MENU_SELECTION)); - menu_add_normal(menu, CLIENT_RESIZE, _("Resi&ze"), acts, TRUE); + menu_add_normal(menu, CLIENT_RESIZE, _("Resi&ze"), NULL, TRUE); - acts = g_slist_prepend(NULL, action_from_string - ("Iconify", OB_USER_ACTION_MENU_SELECTION)); - e = menu_add_normal(menu, CLIENT_ICONIFY, _("Ico&nify"), acts, TRUE); + e = menu_add_normal(menu, CLIENT_ICONIFY, _("Ico&nify"), NULL, TRUE); e->data.normal.mask = ob_rr_theme->iconify_mask; e->data.normal.mask_normal_color = ob_rr_theme->menu_color; e->data.normal.mask_selected_color = ob_rr_theme->menu_selected_color; @@ -316,10 +383,7 @@ void client_menu_startup() e->data.normal.mask_disabled_selected_color = ob_rr_theme->menu_disabled_selected_color; - acts = g_slist_prepend(NULL, action_from_string - ("ToggleMaximizeFull", - OB_USER_ACTION_MENU_SELECTION)); - e = menu_add_normal(menu, CLIENT_MAXIMIZE, _("Ma&ximize"), acts, TRUE); + e = menu_add_normal(menu, CLIENT_MAXIMIZE, _("Ma&ximize"), NULL, TRUE); e->data.normal.mask = ob_rr_theme->max_mask; e->data.normal.mask_normal_color = ob_rr_theme->menu_color; e->data.normal.mask_selected_color = ob_rr_theme->menu_selected_color; @@ -327,9 +391,7 @@ void client_menu_startup() e->data.normal.mask_disabled_selected_color = ob_rr_theme->menu_disabled_selected_color; - acts = g_slist_prepend(NULL, action_from_string - ("ToggleShade", OB_USER_ACTION_MENU_SELECTION)); - e = menu_add_normal(menu, CLIENT_SHADE, _("&Roll up/down"), acts, TRUE); + e = menu_add_normal(menu, CLIENT_SHADE, _("&Roll up/down"), NULL, TRUE); e->data.normal.mask = ob_rr_theme->shade_mask; e->data.normal.mask_normal_color = ob_rr_theme->menu_color; e->data.normal.mask_selected_color = ob_rr_theme->menu_selected_color; @@ -337,10 +399,7 @@ void client_menu_startup() e->data.normal.mask_disabled_selected_color = ob_rr_theme->menu_disabled_selected_color; - acts = g_slist_prepend(NULL, action_from_string - ("ToggleDecorations", - OB_USER_ACTION_MENU_SELECTION)); - menu_add_normal(menu, CLIENT_DECORATE, _("Un/&Decorate"), acts, TRUE); + menu_add_normal(menu, CLIENT_DECORATE, _("Un/&Decorate"), NULL, TRUE); menu_add_separator(menu, -1, NULL); @@ -350,9 +409,7 @@ void client_menu_startup() menu_add_separator(menu, -1, NULL); - acts = g_slist_prepend(NULL, action_from_string - ("Close", OB_USER_ACTION_MENU_SELECTION)); - e = menu_add_normal(menu, CLIENT_CLOSE, _("&Close"), acts, TRUE); + e = menu_add_normal(menu, CLIENT_CLOSE, _("&Close"), NULL, TRUE); e->data.normal.mask = ob_rr_theme->close_mask; e->data.normal.mask_normal_color = ob_rr_theme->menu_color; e->data.normal.mask_selected_color = ob_rr_theme->menu_selected_color; diff --git a/openbox/config.c b/openbox/config.c index 18db15f8..99e35b5a 100644 --- a/openbox/config.c +++ b/openbox/config.c @@ -38,7 +38,6 @@ ObPlacePolicy config_place_policy; gchar *config_theme; gboolean config_theme_keepborder; -gboolean config_theme_hidedisabled; gchar *config_title_layout; @@ -466,13 +465,18 @@ static void parse_theme(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node, g_free(c); } if ((n = parse_find_node("titleLayout", node))) { + gchar *c, *d; + g_free(config_title_layout); config_title_layout = parse_string(doc, n); + + /* replace duplicates with spaces */ + for (c = config_title_layout; *c != '\0'; ++c) + for (d = c+1; *d != '\0'; ++d) + if (*c == *d) *d = ' '; } if ((n = parse_find_node("keepBorder", node))) config_theme_keepborder = parse_bool(doc, n); - if ((n = parse_find_node("hideDisabled", node))) - config_theme_hidedisabled = parse_bool(doc, n); if ((n = parse_find_node("animateIconify", node))) config_animate_iconify = parse_bool(doc, n); @@ -827,7 +831,6 @@ void config_startup(ObParseInst *i) config_animate_iconify = TRUE; config_title_layout = g_strdup("NLIMC"); config_theme_keepborder = TRUE; - config_theme_hidedisabled = FALSE; config_font_activewindow = NULL; config_font_inactivewindow = NULL; diff --git a/openbox/config.h b/openbox/config.h index 41cf7482..94991a60 100644 --- a/openbox/config.h +++ b/openbox/config.h @@ -111,8 +111,6 @@ extern gchar *config_theme; /*! Show the one-pixel border after toggleDecor */ extern gboolean config_theme_keepborder; -/*! Hide window frame buttons that the window doesn't allow */ -extern gboolean config_theme_hidedisabled; /*! Titlebar button layout */ extern gchar *config_title_layout; /*! Animate windows iconifying and restoring */ diff --git a/openbox/event.c b/openbox/event.c index 44ae7b0a..babb5197 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -32,6 +32,7 @@ #include "menuframe.h" #include "keyboard.h" #include "modkeys.h" +#include "propwin.h" #include "mouse.h" #include "mainloop.h" #include "framerender.h" @@ -81,7 +82,7 @@ static gboolean event_handle_menu(XEvent *e); static void event_handle_dock(ObDock *s, XEvent *e); static void event_handle_dockapp(ObDockApp *app, XEvent *e); static void event_handle_client(ObClient *c, XEvent *e); -static void event_handle_group(ObGroup *g, XEvent *e); +static void event_handle_user_time_window_clients(GSList *l, XEvent *e); static void event_handle_user_input(ObClient *client, XEvent *e); static void focus_delay_dest(gpointer data); @@ -406,11 +407,11 @@ static gboolean event_ignore(XEvent *e, ObClient *client) static void event_process(const XEvent *ec, gpointer data) { Window window; - ObGroup *group = NULL; ObClient *client = NULL; ObDock *dock = NULL; ObDockApp *dockapp = NULL; ObWindow *obwin = NULL; + GSList *timewinclients = NULL; XEvent ee, *e; ObEventData *ed = data; @@ -419,8 +420,9 @@ static void event_process(const XEvent *ec, gpointer data) e = ⅇ window = event_get_window(e); - if (!(e->type == PropertyNotify && - (group = g_hash_table_lookup(group_map, &window)))) + if (e->type != PropertyNotify || + !(timewinclients = propwin_get_clients(window, + OB_PROPWIN_USER_TIME))) if ((obwin = g_hash_table_lookup(window_map, &window))) { switch (obwin->type) { case Window_Dock: @@ -554,8 +556,8 @@ static void event_process(const XEvent *ec, gpointer data) /* focus_set_client has already been called for sure */ client_calc_layer(client); } - } else if (group) - event_handle_group(group, e); + } else if (timewinclients) + event_handle_user_time_window_clients(timewinclients, e); else if (client) event_handle_client(client, e); else if (dockapp) @@ -662,21 +664,11 @@ static void event_handle_root(XEvent *e) } } -static void event_handle_group(ObGroup *group, XEvent *e) -{ - GSList *it; - - g_assert(e->type == PropertyNotify); - - for (it = group->members; it; it = g_slist_next(it)) - event_handle_client(it->data, e); -} - void event_enter_client(ObClient *client) { g_assert(config_focus_follow); - if (client_normal(client) && client_can_focus(client)) { + if (client_enter_focusable(client) && client_can_focus(client)) { if (config_focus_delay) { ObFocusDelayData *data; @@ -699,6 +691,15 @@ void event_enter_client(ObClient *client) } } +static void event_handle_user_time_window_clients(GSList *l, XEvent *e) +{ + g_assert(e->type == PropertyNotify); + if (e->xproperty.atom == prop_atoms.net_wm_user_time) { + for (; l; l = g_slist_next(l)) + client_update_user_time(l->data); + } +} + static void event_handle_client(ObClient *client, XEvent *e) { XEvent ce; @@ -1191,6 +1192,9 @@ static void event_handle_client(ObClient *client, XEvent *e) else if (msgtype == prop_atoms.net_wm_user_time) { client_update_user_time(client); } + else if (msgtype == prop_atoms.net_wm_user_time_window) { + client_update_user_time_window(client); + } #ifdef SYNC else if (msgtype == prop_atoms.net_wm_sync_request_counter) { client_update_sync_request_counter(client); diff --git a/openbox/frame.c b/openbox/frame.c index be4e688d..2c3fb58f 100644 --- a/openbox/frame.c +++ b/openbox/frame.c @@ -48,10 +48,21 @@ #define FRAME_HANDLE_Y(f) (f->innersize.top + f->client->area.height + \ f->cbwidth_y) -static void layout_title(ObFrame *self); +/* the offsets for the titlebar elements from the edge of the titlebar. + negative means from the right edge. */ +gint icon_off; +gint label_off; +gint iconify_off; +gint desk_off; +gint shade_off; +gint max_off; +gint close_off; + + static void flash_done(gpointer data); static gboolean flash_timeout(gpointer data); +static void layout_title(ObFrame *self); static void set_theme_statics(ObFrame *self); static void free_theme_statics(ObFrame *self); static gboolean frame_animate_iconify(gpointer self); @@ -369,15 +380,6 @@ void frame_adjust_area(ObFrame *self, gboolean moved, self->innersize.bottom += ob_rr_theme->handle_height + self->rbwidth + (self->rbwidth - self->bwidth); - /* they all default off, they're turned on in layout_title */ - self->icon_x = -1; - self->desk_x = -1; - self->shade_x = -1; - self->iconify_x = -1; - self->label_x = -1; - self->max_x = -1; - self->close_x = -1; - /* position/size and map/unmap all the windows */ if (!fake) { @@ -408,7 +410,7 @@ void frame_adjust_area(ObFrame *self, gboolean moved, XUnmapWindow(ob_display, self->title); } - if (self->decorations & OB_FRAME_DECOR_TITLEBAR) + if ((self->decorations & OB_FRAME_DECOR_TITLEBAR)) /* layout the title bar elements */ layout_title(self); @@ -572,11 +574,12 @@ void frame_grab_client(ObFrame *self, ObClient *client) req's) the ButtonPress is to catch clicks on the client border */ XSelectInput(ob_display, self->plate, PLATE_EVENTMASK); - frame_adjust_area(self, TRUE, TRUE, FALSE); - /* map the client so it maps when the frame does */ XMapWindow(ob_display, client->window); + /* adjust the frame to the client's size */ + frame_adjust_area(self, FALSE, TRUE, FALSE); + /* set all the windows for the frame in the window_map */ g_hash_table_insert(window_map, &self->window, client); g_hash_table_insert(window_map, &self->plate, client); @@ -661,139 +664,156 @@ void frame_release_client(ObFrame *self, ObClient *client) frame_free(self); } +/* is there anything present between us and the label? */ +static gboolean is_button_present(ObFrame *self, const gchar *lc, gint dir) { + for (; *lc != '\0' && lc >= config_title_layout; lc += dir) { + if (*lc == ' ') continue; /* it was invalid */ + if (*lc == 'N' && self->decorations & OB_FRAME_DECOR_ICON) + return TRUE; + if (*lc == 'D' && self->decorations & OB_FRAME_DECOR_ALLDESKTOPS) + return TRUE; + if (*lc == 'S' && self->decorations & OB_FRAME_DECOR_SHADE) + return TRUE; + if (*lc == 'I' && self->decorations & OB_FRAME_DECOR_ICONIFY) + return TRUE; + if (*lc == 'M' && self->decorations & OB_FRAME_DECOR_MAXIMIZE) + return TRUE; + if (*lc == 'C' && self->decorations & OB_FRAME_DECOR_CLOSE) + return TRUE; + if (*lc == 'L') return FALSE; + } + return FALSE; +} + static void layout_title(ObFrame *self) { gchar *lc; - gint x; - gboolean n, d, i, l, m, c, s; + gint i, x; - n = d = i = l = m = c = s = FALSE; + const gint bwidth = ob_rr_theme->button_size + ob_rr_theme->paddingx + 1; + /* position of the left most button */ + const gint left = ob_rr_theme->paddingx + 1; + /* position of the right most button */ + const gint right = self->width - bwidth; - /* figure out whats being shown, and the width of the label */ + /* turn them all off */ + self->icon_on = self->desk_on = self->shade_on = self->iconify_on = + self->max_on = self->close_on = self->label_on = FALSE; self->label_width = self->width - (ob_rr_theme->paddingx + 1) * 2; - for (lc = config_title_layout; *lc != '\0'; ++lc) { - switch (*lc) { - case 'N': - if (n) { *lc = ' '; break; } /* rm duplicates */ - n = TRUE; - self->label_width -= (ob_rr_theme->button_size + 2 + - ob_rr_theme->paddingx + 1); - break; - case 'D': - if (d) { *lc = ' '; break; } - if (!(self->decorations & OB_FRAME_DECOR_ALLDESKTOPS) - && config_theme_hidedisabled) - break; - d = TRUE; - self->label_width -= (ob_rr_theme->button_size + - ob_rr_theme->paddingx + 1); - break; - case 'S': - if (s) { *lc = ' '; break; } - if (!(self->decorations & OB_FRAME_DECOR_SHADE) - && config_theme_hidedisabled) - break; - s = TRUE; - self->label_width -= (ob_rr_theme->button_size + - ob_rr_theme->paddingx + 1); - break; - case 'I': - if (i) { *lc = ' '; break; } - if (!(self->decorations & OB_FRAME_DECOR_ICONIFY) - && config_theme_hidedisabled) - break; - i = TRUE; - self->label_width -= (ob_rr_theme->button_size + - ob_rr_theme->paddingx + 1); - break; - case 'L': - if (l) { *lc = ' '; break; } - l = TRUE; - break; - case 'M': - if (m) { *lc = ' '; break; } - if (!(self->decorations & OB_FRAME_DECOR_MAXIMIZE) - && config_theme_hidedisabled) - break; - m = TRUE; - self->label_width -= (ob_rr_theme->button_size + - ob_rr_theme->paddingx + 1); - break; - case 'C': - if (c) { *lc = ' '; break; } - if (!(self->decorations & OB_FRAME_DECOR_CLOSE) - && config_theme_hidedisabled) - break; - c = TRUE; - self->label_width -= (ob_rr_theme->button_size + - ob_rr_theme->paddingx + 1); - break; - } - } - if (self->label_width < 1) self->label_width = 1; - - if (!n) XUnmapWindow(ob_display, self->icon); - if (!d) XUnmapWindow(ob_display, self->desk); - if (!s) XUnmapWindow(ob_display, self->shade); - if (!i) XUnmapWindow(ob_display, self->iconify); - if (!l) XUnmapWindow(ob_display, self->label); - if (!m) XUnmapWindow(ob_display, self->max); - if (!c) XUnmapWindow(ob_display, self->close); - - x = ob_rr_theme->paddingx + 1; - for (lc = config_title_layout; *lc != '\0'; ++lc) { - switch (*lc) { - case 'N': - if (!n) break; - self->icon_x = x; - XMapWindow(ob_display, self->icon); - XMoveWindow(ob_display, self->icon, x, ob_rr_theme->paddingy); - x += ob_rr_theme->button_size + 2 + ob_rr_theme->paddingx + 1; - break; - case 'D': - if (!d) break; - self->desk_x = x; - XMapWindow(ob_display, self->desk); - XMoveWindow(ob_display, self->desk, x, ob_rr_theme->paddingy + 1); - x += ob_rr_theme->button_size + ob_rr_theme->paddingx + 1; - break; - case 'S': - if (!s) break; - self->shade_x = x; - XMapWindow(ob_display, self->shade); - XMoveWindow(ob_display, self->shade, x, ob_rr_theme->paddingy + 1); - x += ob_rr_theme->button_size + ob_rr_theme->paddingx + 1; - break; - case 'I': - if (!i) break; - self->iconify_x = x; - XMapWindow(ob_display, self->iconify); - XMoveWindow(ob_display,self->iconify, x, ob_rr_theme->paddingy + 1); - x += ob_rr_theme->button_size + ob_rr_theme->paddingx + 1; - break; - case 'L': - if (!l) break; - self->label_x = x; - XMapWindow(ob_display, self->label); - XMoveWindow(ob_display, self->label, x, ob_rr_theme->paddingy); - x += self->label_width + ob_rr_theme->paddingx + 1; - break; - case 'M': - if (!m) break; - self->max_x = x; - XMapWindow(ob_display, self->max); - XMoveWindow(ob_display, self->max, x, ob_rr_theme->paddingy + 1); - x += ob_rr_theme->button_size + ob_rr_theme->paddingx + 1; - break; - case 'C': - if (!c) break; - self->close_x = x; - XMapWindow(ob_display, self->close); - XMoveWindow(ob_display, self->close, x, ob_rr_theme->paddingy + 1); - x += ob_rr_theme->button_size + ob_rr_theme->paddingx + 1; - break; + + /* figure out what's being show, find each element's position, and the + width of the label + + do the ones before the label, then after the label, + i will be +1 the first time through when working to the left, + and -1 the second time through when working to the right */ + for (i = 1; i >= -1; i-=2) { + if (i > 0) { + x = left; + lc = config_title_layout; + } else { + x = right; + lc = config_title_layout + strlen(config_title_layout)-1; } + + /* stop at the end of the string (or the label, which calls break) */ + for (; *lc != '\0' && lc >= config_title_layout; lc+=i) + if (*lc == 'L') { + if (i > 0) { + self->label_on = TRUE; + self->label_x = x; + } + break; /* break the for loop, do other side of label */ + } else if (*lc == 'N') { + if ((self->icon_on = is_button_present(self, lc, i))) { + /* icon gets extra padding */ + self->label_width -= bwidth + 2; + self->icon_x = x + (i * 1); + x += i * (bwidth + 2); + } + } else if (*lc == 'D') { + if ((self->desk_on = is_button_present(self, lc, i))) { + self->label_width -= bwidth; + self->desk_x = x; + x += i * bwidth; + } + } else if (*lc == 'S') { + if ((self->shade_on = is_button_present(self, lc, i))) { + self->label_width -= bwidth; + self->shade_x = x; + x += i * bwidth; + } + } else if (*lc == 'I') { + if ((self->iconify_on = is_button_present(self, lc, i))) { + self->label_width -= bwidth; + self->iconify_x = x; + x += i * bwidth; + } + } else if (*lc == 'M') { + if ((self->max_on = is_button_present(self, lc, i))) { + self->label_width -= bwidth; + self->max_x = x; + x += i * bwidth; + } + } else if (*lc == 'C') { + if ((self->close_on = is_button_present(self, lc, i))) { + self->label_width -= bwidth; + self->close_x = x; + x += i * bwidth; + } + } } + + /* position and map the elements */ + if (self->icon_on) { + XMapWindow(ob_display, self->icon); + XMoveWindow(ob_display, self->icon, self->icon_x, + ob_rr_theme->paddingy); + } else + XUnmapWindow(ob_display, self->icon); + + if (self->desk_on) { + XMapWindow(ob_display, self->desk); + XMoveWindow(ob_display, self->desk, self->desk_x, + ob_rr_theme->paddingy + 1); + } else + XUnmapWindow(ob_display, self->desk); + + if (self->shade_on) { + XMapWindow(ob_display, self->shade); + XMoveWindow(ob_display, self->shade, self->shade_x, + ob_rr_theme->paddingy + 1); + } else + XUnmapWindow(ob_display, self->shade); + + if (self->iconify_on) { + XMapWindow(ob_display, self->iconify); + XMoveWindow(ob_display, self->iconify, self->iconify_x, + ob_rr_theme->paddingy + 1); + } else + XUnmapWindow(ob_display, self->iconify); + + if (self->max_on) { + XMapWindow(ob_display, self->max); + XMoveWindow(ob_display, self->max, self->max_x, + ob_rr_theme->paddingy + 1); + } else + XUnmapWindow(ob_display, self->max); + + if (self->close_on) { + XMapWindow(ob_display, self->close); + XMoveWindow(ob_display, self->close, self->close_x, + ob_rr_theme->paddingy + 1); + } else + XUnmapWindow(ob_display, self->close); + + if (self->label_on) { + self->label_width = MAX(1, self->label_width); /* no lower than 1 */ + XMapWindow(ob_display, self->label); + XMoveWindow(ob_display, self->label, self->label_x, + ob_rr_theme->paddingy); + } else + XUnmapWindow(ob_display, self->label); } ObFrameContext frame_context_from_string(const gchar *name) diff --git a/openbox/frame.h b/openbox/frame.h index 7be63d53..3a5dfdb2 100644 --- a/openbox/frame.h +++ b/openbox/frame.h @@ -114,8 +114,16 @@ struct _ObFrame GSList *clients; - gint width; /* title and handle */ - gint label_width; + gint icon_on; /* if the window icon button is on */ + gint label_on; /* if the window title is on */ + gint iconify_on; /* if the window iconify button is on */ + gint desk_on; /* if the window all-desktops button is on */ + gint shade_on; /* if the window shade button is on */ + gint max_on; /* if the window maximize button is on */ + gint close_on; /* if the window close button is on */ + + gint width; /* width of the titlebar and handle */ + gint label_width; /* width of the label in the titlebar */ gint icon_x; /* x-position of the window icon button */ gint label_x; /* x-position of the window title */ gint iconify_x; /* x-position of the window iconify button */ diff --git a/openbox/framerender.c b/openbox/framerender.c index f60039c8..fb4340e9 100644 --- a/openbox/framerender.c +++ b/openbox/framerender.c @@ -241,7 +241,7 @@ void framerender_frame(ObFrame *self) static void framerender_label(ObFrame *self, RrAppearance *a) { - if (self->label_x < 0) return; + if (!self->label_on) return; /* set the texture's text! */ a->texture[0].data.text.string = self->client->title; RrPaint(a, self->label, self->label_width, ob_rr_theme->label_height); @@ -251,7 +251,7 @@ static void framerender_icon(ObFrame *self, RrAppearance *a) { const ObClientIcon *icon; - if (self->icon_x < 0) return; + if (!self->icon_on) return; icon = client_icon(self->client, ob_rr_theme->button_size + 2, @@ -270,33 +270,33 @@ static void framerender_icon(ObFrame *self, RrAppearance *a) static void framerender_max(ObFrame *self, RrAppearance *a) { - if (self->max_x < 0) return; + if (!self->max_on) return; RrPaint(a, self->max, ob_rr_theme->button_size, ob_rr_theme->button_size); } static void framerender_iconify(ObFrame *self, RrAppearance *a) { - if (self->iconify_x < 0) return; + if (!self->iconify_on) return; RrPaint(a, self->iconify, ob_rr_theme->button_size, ob_rr_theme->button_size); } static void framerender_desk(ObFrame *self, RrAppearance *a) { - if (self->desk_x < 0) return; + if (!self->desk_on) return; RrPaint(a, self->desk, ob_rr_theme->button_size, ob_rr_theme->button_size); } static void framerender_shade(ObFrame *self, RrAppearance *a) { - if (self->shade_x < 0) return; + if (!self->shade_on) return; RrPaint(a, self->shade, ob_rr_theme->button_size, ob_rr_theme->button_size); } static void framerender_close(ObFrame *self, RrAppearance *a) { - if (self->close_x < 0) return; + if (!self->close_on) return; RrPaint(a, self->close, ob_rr_theme->button_size, ob_rr_theme->button_size); } diff --git a/openbox/group.c b/openbox/group.c index f70b84b7..c0ba6ed7 100644 --- a/openbox/group.c +++ b/openbox/group.c @@ -19,17 +19,17 @@ #include "group.h" #include "client.h" -GHashTable *group_map = NULL; +static GHashTable *group_map; -static guint map_hash(Window *w) { return *w; } -static gboolean map_key_comp(Window *w1, Window *w2) { return *w1 == *w2; } +static guint window_hash(Window *w) { return *w; } +static gboolean window_comp(Window *w1, Window *w2) { return *w1 == *w2; } void group_startup(gboolean reconfig) { if (reconfig) return; - group_map = g_hash_table_new((GHashFunc)map_hash, - (GEqualFunc)map_key_comp); + group_map = g_hash_table_new((GHashFunc)window_hash, + (GEqualFunc)window_comp); } void group_shutdown(gboolean reconfig) diff --git a/openbox/group.h b/openbox/group.h index 844b629b..86b36b4c 100644 --- a/openbox/group.h +++ b/openbox/group.h @@ -34,8 +34,6 @@ struct _ObGroup GSList *members; }; -extern GHashTable *group_map; - void group_startup(gboolean reconfig); void group_shutdown(gboolean reconfig); diff --git a/openbox/keyboard.c b/openbox/keyboard.c index cf56ad8f..d8f35bcc 100644 --- a/openbox/keyboard.c +++ b/openbox/keyboard.c @@ -78,9 +78,11 @@ static gboolean chain_timeout(gpointer data) static void set_curpos(KeyBindingTree *newpos) { - grab_keys(FALSE); - curpos = newpos; - grab_keys(TRUE); + if (curpos != newpos) { + grab_keys(FALSE); + curpos = newpos; + grab_keys(TRUE); + } if (curpos != NULL) { gchar *text = NULL; @@ -247,7 +249,7 @@ gboolean keyboard_process_interactive_grab(const XEvent *e, ObClient **client) handled = TRUE; } } else if (e->type == ButtonPress) { - cancel = FALSE; + cancel = TRUE; done = TRUE; handled = FALSE; } diff --git a/openbox/menu.h b/openbox/menu.h index 9fc84bb8..990e946c 100644 --- a/openbox/menu.h +++ b/openbox/menu.h @@ -42,6 +42,8 @@ typedef void (*ObMenuHideFunc)(struct _ObMenuFrame *frame, gpointer data); typedef gboolean (*ObMenuUpdateFunc)(struct _ObMenuFrame *frame, gpointer data); typedef void (*ObMenuExecuteFunc)(struct _ObMenuEntry *entry, + struct _ObMenuFrame *frame, + struct _ObClient *client, guint state, gpointer data, Time time); typedef void (*ObMenuDestroyFunc)(struct _ObMenu *menu, gpointer data); /*! @param x is the mouse x coordinate. on return it should be the x coordinate diff --git a/openbox/menuframe.c b/openbox/menuframe.c index 01d3ae1f..5ec8280d 100644 --- a/openbox/menuframe.c +++ b/openbox/menuframe.c @@ -43,7 +43,6 @@ GList *menu_frame_visible; static ObMenuEntryFrame* menu_entry_frame_new(ObMenuEntry *entry, ObMenuFrame *frame); static void menu_entry_frame_free(ObMenuEntryFrame *self); -static void menu_frame_render(ObMenuFrame *self); static void menu_frame_update(ObMenuFrame *self); static gboolean menu_entry_frame_submenu_timeout(gpointer data); @@ -616,7 +615,7 @@ static gint menu_entry_frame_get_height(ObMenuEntryFrame *self, return h; } -static void menu_frame_render(ObMenuFrame *self) +void menu_frame_render(ObMenuFrame *self) { gint w = 0, h = 0; gint tw, th; /* temps */ @@ -1230,13 +1229,16 @@ void menu_entry_frame_execute(ObMenuEntryFrame *self, guint state, Time time) gpointer data = self->frame->menu->data; GSList *acts = self->entry->data.normal.actions; ObClient *client = self->frame->client; + ObMenuFrame *frame = self->frame; /* release grabs before executing the shit */ - if (!(state & ControlMask)) + if (!(state & ControlMask)) { menu_frame_hide_all(); + frame = NULL; + } if (func) - func(entry, state, data, time); + func(entry, frame, client, state, data, time); else action_run(acts, client, state, time); } diff --git a/openbox/menuframe.h b/openbox/menuframe.h index 0ce96158..4f896ec8 100644 --- a/openbox/menuframe.h +++ b/openbox/menuframe.h @@ -133,6 +133,8 @@ void menu_frame_hide(ObMenuFrame *self); void menu_frame_hide_all(); void menu_frame_hide_all_client(struct _ObClient *client); +void menu_frame_render(ObMenuFrame *self); + void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry, gboolean immediate); void menu_frame_select_previous(ObMenuFrame *self); diff --git a/openbox/moveresize.c b/openbox/moveresize.c index b0b1f2a1..6a1e2354 100644 --- a/openbox/moveresize.c +++ b/openbox/moveresize.c @@ -37,6 +37,9 @@ #include #include +/* how far windows move and resize with the keyboard arrows */ +#define KEY_DIST 4 + gboolean moveresize_in_progress = FALSE; ObClient *moveresize_client = NULL; #ifdef SYNC @@ -296,20 +299,23 @@ void moveresize_end(gboolean cancel) moveresize_client = NULL; } -static void do_move(gboolean resist) +static void do_move(gboolean keyboard) { - if (resist) { - resist_move_windows(moveresize_client, &cur_x, &cur_y); - resist_move_monitors(moveresize_client, &cur_x, &cur_y); - } + gint resist; + + if (keyboard) resist = KEY_DIST - 1; /* resist for one key press */ + else resist = config_resist_win; + resist_move_windows(moveresize_client, resist, &cur_x, &cur_y); + if (!keyboard) resist = config_resist_edge; + resist_move_monitors(moveresize_client, resist, &cur_x, &cur_y); client_configure(moveresize_client, cur_x, cur_y, moveresize_client->area.width, moveresize_client->area.height, TRUE, FALSE); if (config_resize_popup_show == 2) /* == "Always" */ popup_coords(moveresize_client, "%d x %d", - moveresize_client->frame->area.x, - moveresize_client->frame->area.y); + moveresize_client->frame->area.x, + moveresize_client->frame->area.y); } static void do_resize() @@ -378,18 +384,21 @@ static void do_resize() moveresize_client->logical_size.height); } -static void calc_resize(gboolean resist) +static void calc_resize(gboolean keyboard) { + gint resist; + /* resist_size_* needs the frame size */ cur_x += moveresize_client->frame->size.left + moveresize_client->frame->size.right; cur_y += moveresize_client->frame->size.top + moveresize_client->frame->size.bottom; - if (resist) { - resist_size_windows(moveresize_client, &cur_x, &cur_y, lockcorner); - resist_size_monitors(moveresize_client, &cur_x, &cur_y, lockcorner); - } + if (keyboard) resist = KEY_DIST - 1; /* resist for one key press */ + else resist = config_resist_win; + resist_size_windows(moveresize_client, resist, &cur_x, &cur_y, lockcorner); + if (!keyboard) resist = config_resist_edge; + resist_size_monitors(moveresize_client, resist, &cur_x, &cur_y,lockcorner); cur_x -= moveresize_client->frame->size.left + moveresize_client->frame->size.right; @@ -419,7 +428,7 @@ gboolean moveresize_event(XEvent *e) if (moving) { cur_x = start_cx + e->xmotion.x_root - start_x; cur_y = start_cy + e->xmotion.y_root - start_y; - do_move(TRUE); + do_move(FALSE); } else { if (corner == prop_atoms.net_wm_moveresize_size_topleft) { cur_x = start_cw - (e->xmotion.x_root - start_x); @@ -462,7 +471,7 @@ gboolean moveresize_event(XEvent *e) } else g_assert_not_reached(); - calc_resize(TRUE); + calc_resize(FALSE); do_resize(); } used = TRUE; @@ -482,13 +491,13 @@ gboolean moveresize_event(XEvent *e) gint dx = 0, dy = 0, ox = cur_x, oy = cur_y; if (e->xkey.keycode == ob_keycode(OB_KEY_RIGHT)) - dx = MAX(4, moveresize_client->size_inc.width); + dx = MAX(KEY_DIST, moveresize_client->size_inc.width); else if (e->xkey.keycode == ob_keycode(OB_KEY_LEFT)) - dx = -MAX(4, moveresize_client->size_inc.width); + dx = -MAX(KEY_DIST, moveresize_client->size_inc.width); else if (e->xkey.keycode == ob_keycode(OB_KEY_DOWN)) - dy = MAX(4, moveresize_client->size_inc.height); + dy = MAX(KEY_DIST, moveresize_client->size_inc.height); else /* if (e->xkey.keycode == ob_keycode(OB_KEY_UP)) */ - dy = -MAX(4, moveresize_client->size_inc.height); + dy = -MAX(KEY_DIST, moveresize_client->size_inc.height); cur_x += dx; cur_y += dy; @@ -500,7 +509,8 @@ gboolean moveresize_event(XEvent *e) while (XCheckTypedEvent(ob_display, MotionNotify, &ce)); } - do_resize(FALSE); + calc_resize(TRUE); + do_resize(); /* because the cursor moves even though the window does not nessesarily (resistance), this adjusts where the curor @@ -515,13 +525,13 @@ gboolean moveresize_event(XEvent *e) gint opx, px, opy, py; if (e->xkey.keycode == ob_keycode(OB_KEY_RIGHT)) - dx = 4; + dx = KEY_DIST; else if (e->xkey.keycode == ob_keycode(OB_KEY_LEFT)) - dx = -4; + dx = -KEY_DIST; else if (e->xkey.keycode == ob_keycode(OB_KEY_DOWN)) - dy = 4; + dy = KEY_DIST; else /* if (e->xkey.keycode == ob_keycode(OB_KEY_UP)) */ - dy = -4; + dy = -KEY_DIST; cur_x += dx; cur_y += dy; @@ -535,7 +545,7 @@ gboolean moveresize_event(XEvent *e) } screen_pointer_pos(&px, &py); - do_move(FALSE); + do_move(TRUE); /* because the cursor moves even though the window does not nessesarily (resistance), this adjusts where the curor diff --git a/openbox/moveresize.h b/openbox/moveresize.h index ec5ce10d..2f8d3e6a 100644 --- a/openbox/moveresize.h +++ b/openbox/moveresize.h @@ -36,6 +36,7 @@ extern XSyncAlarm moveresize_alarm; void moveresize_startup(gboolean reconfig); void moveresize_shutdown(gboolean reconfig); +/*! @param corner This is one of the prop_atoms.net_wm_moveresize_ atoms */ void moveresize_start(struct _ObClient *c, gint x, gint y, guint button, guint32 corner); void moveresize_end(gboolean cancel); diff --git a/openbox/openbox.c b/openbox/openbox.c index 9cb38b56..db26f0d2 100644 --- a/openbox/openbox.c +++ b/openbox/openbox.c @@ -38,6 +38,7 @@ #include "menuframe.h" #include "grab.h" #include "group.h" +#include "propwin.h" #include "config.h" #include "mainloop.h" #include "gettext.h" @@ -282,6 +283,7 @@ gint main(gint argc, gchar **argv) sn_startup(reconfigure); screen_startup(reconfigure); grab_startup(reconfigure); + propwin_startup(reconfigure); group_startup(reconfigure); client_startup(reconfigure); dock_startup(reconfigure); @@ -339,6 +341,7 @@ gint main(gint argc, gchar **argv) dock_shutdown(reconfigure); client_shutdown(reconfigure); group_shutdown(reconfigure); + propwin_shutdown(reconfigure); grab_shutdown(reconfigure); screen_shutdown(reconfigure); focus_shutdown(reconfigure); diff --git a/openbox/place.c b/openbox/place.c index f37973b3..214bb59c 100644 --- a/openbox/place.c +++ b/openbox/place.c @@ -425,7 +425,7 @@ static gboolean place_per_app_setting(ObClient *client, gint *x, gint *y, static gboolean place_transient(ObClient *client, gint *x, gint *y) { - if (client->transient_for) { + if (client->transient_for && client->type == OB_CLIENT_TYPE_DIALOG) { if (client->transient_for != OB_TRAN_GROUP) { ObClient *c = client; ObClient *p = client->transient_for; diff --git a/openbox/prop.c b/openbox/prop.c index 0485045e..704c9109 100644 --- a/openbox/prop.c +++ b/openbox/prop.c @@ -92,6 +92,7 @@ void prop_startup() /* CREATE(net_wm_pid, "_NET_WM_PID"); */ CREATE(net_wm_allowed_actions, "_NET_WM_ALLOWED_ACTIONS"); CREATE(net_wm_user_time, "_NET_WM_USER_TIME"); + CREATE(net_wm_user_time_window, "_NET_WM_USER_TIME_WINDOW"); CREATE(kde_net_wm_frame_strut, "_KDE_NET_WM_FRAME_STRUT"); CREATE(net_frame_extents, "_NET_FRAME_EXTENTS"); diff --git a/openbox/prop.h b/openbox/prop.h index eaa1bf2d..f8b44a73 100644 --- a/openbox/prop.h +++ b/openbox/prop.h @@ -130,6 +130,7 @@ typedef struct Atoms { /* Atom net_wm_pid; */ Atom net_wm_allowed_actions; Atom net_wm_user_time; + Atom net_wm_user_time_window; Atom net_frame_extents; /* application protocols */ diff --git a/openbox/resist.c b/openbox/resist.c index e5d49faa..077c4667 100644 --- a/openbox/resist.c +++ b/openbox/resist.c @@ -26,7 +26,7 @@ #include -void resist_move_windows(ObClient *c, gint *x, gint *y) +void resist_move_windows(ObClient *c, gint resist, gint *x, gint *y) { GList *it; gint l, t, r, b; /* requested edges */ @@ -34,6 +34,8 @@ void resist_move_windows(ObClient *c, gint *x, gint *y) gint w, h; /* current size */ ObClient *snapx = NULL, *snapy = NULL; + if (!resist) return; + w = c->frame->area.width; h = c->frame->area.height; @@ -47,73 +49,72 @@ void resist_move_windows(ObClient *c, gint *x, gint *y) cr = RECT_RIGHT(c->frame->area); cb = RECT_BOTTOM(c->frame->area); - if (config_resist_win) - for (it = stacking_list; it; it = g_list_next(it)) { - ObClient *target; - gint tl, tt, tr, tb; /* 1 past the target's edges on each side */ - - if (!WINDOW_IS_CLIENT(it->data)) - continue; - target = it->data; - - /* don't snap to self or non-visibles */ - if (!target->frame->visible || target == c) continue; - - /* don't snap to windows in layers beneath */ - if(target->layer < c->layer && !config_resist_layers_below) - continue; - - tl = RECT_LEFT(target->frame->area) - 1; - tt = RECT_TOP(target->frame->area) - 1; - tr = RECT_RIGHT(target->frame->area) + 1; - tb = RECT_BOTTOM(target->frame->area) + 1; - - /* snapx and snapy ensure that the window snaps to the top-most - window edge available, without going all the way from - bottom-to-top in the stacking list - */ - if (snapx == NULL) { - if (ct < tb && cb > tt) { - if (cl >= tr && l < tr && l >= tr - config_resist_win) - *x = tr, snapx = target; - else if (cr <= tl && r > tl && - r <= tl + config_resist_win) - *x = tl - w + 1, snapx = target; - if (snapx != NULL) { - /* try to corner snap to the window */ - if (ct > tt && t <= tt && - t > tt - config_resist_win) - *y = tt + 1, snapy = target; - else if (cb < tb && b >= tb && - b < tb + config_resist_win) - *y = tb - h, snapy = target; - } + for (it = stacking_list; it; it = g_list_next(it)) { + ObClient *target; + gint tl, tt, tr, tb; /* 1 past the target's edges on each side */ + + if (!WINDOW_IS_CLIENT(it->data)) + continue; + target = it->data; + + /* don't snap to self or non-visibles */ + if (!target->frame->visible || target == c) continue; + + /* don't snap to windows in layers beneath */ + if(target->layer < c->layer && !config_resist_layers_below) + continue; + + tl = RECT_LEFT(target->frame->area) - 1; + tt = RECT_TOP(target->frame->area) - 1; + tr = RECT_RIGHT(target->frame->area) + 1; + tb = RECT_BOTTOM(target->frame->area) + 1; + + /* snapx and snapy ensure that the window snaps to the top-most + window edge available, without going all the way from + bottom-to-top in the stacking list + */ + if (snapx == NULL) { + if (ct < tb && cb > tt) { + if (cl >= tr && l < tr && l >= tr - resist) + *x = tr, snapx = target; + else if (cr <= tl && r > tl && + r <= tl + resist) + *x = tl - w + 1, snapx = target; + if (snapx != NULL) { + /* try to corner snap to the window */ + if (ct > tt && t <= tt && + t > tt - resist) + *y = tt + 1, snapy = target; + else if (cb < tb && b >= tb && + b < tb + resist) + *y = tb - h, snapy = target; } } - if (snapy == NULL) { - if (cl < tr && cr > tl) { - if (ct >= tb && t < tb && t >= tb - config_resist_win) - *y = tb, snapy = target; - else if (cb <= tt && b > tt && - b <= tt + config_resist_win) - *y = tt - h + 1, snapy = target; - if (snapy != NULL) { - /* try to corner snap to the window */ - if (cl > tl && l <= tl && - l > tl - config_resist_win) - *x = tl + 1, snapx = target; - else if (cr < tr && r >= tr && - r < tr + config_resist_win) - *x = tr - w, snapx = target; - } + } + if (snapy == NULL) { + if (cl < tr && cr > tl) { + if (ct >= tb && t < tb && t >= tb - resist) + *y = tb, snapy = target; + else if (cb <= tt && b > tt && + b <= tt + resist) + *y = tt - h + 1, snapy = target; + if (snapy != NULL) { + /* try to corner snap to the window */ + if (cl > tl && l <= tl && + l > tl - resist) + *x = tl + 1, snapx = target; + else if (cr < tr && r >= tr && + r < tr + resist) + *x = tr - w, snapx = target; } } - - if (snapx && snapy) break; } + + if (snapx && snapy) break; + } } -void resist_move_monitors(ObClient *c, gint *x, gint *y) +void resist_move_monitors(ObClient *c, gint resist, gint *x, gint *y) { Rect *area, *parea; guint i; @@ -123,6 +124,8 @@ void resist_move_monitors(ObClient *c, gint *x, gint *y) gint cl, ct, cr, cb; /* current edges */ gint w, h; /* current size */ + if (!resist) return; + w = c->frame->area.width; h = c->frame->area.height; @@ -136,45 +139,44 @@ void resist_move_monitors(ObClient *c, gint *x, gint *y) cr = RECT_RIGHT(c->frame->area); cb = RECT_BOTTOM(c->frame->area); - if (config_resist_edge) { - for (i = 0; i < screen_num_monitors; ++i) { - area = screen_area_monitor(c->desktop, i); - parea = screen_physical_area_monitor(i); - - if (!RECT_INTERSECTS_RECT(*parea, c->frame->area)) - continue; - - al = RECT_LEFT(*area); - at = RECT_TOP(*area); - ar = RECT_RIGHT(*area); - ab = RECT_BOTTOM(*area); - pl = RECT_LEFT(*parea); - pt = RECT_TOP(*parea); - pr = RECT_RIGHT(*parea); - pb = RECT_BOTTOM(*parea); - - if (cl >= al && l < al && l >= al - config_resist_edge) - *x = al; - else if (cr <= ar && r > ar && r <= ar + config_resist_edge) - *x = ar - w + 1; - else if (cl >= pl && l < pl && l >= pl - config_resist_edge) - *x = pl; - else if (cr <= pr && r > pr && r <= pr + config_resist_edge) - *x = pr - w + 1; - - if (ct >= at && t < at && t >= at - config_resist_edge) - *y = at; - else if (cb <= ab && b > ab && b < ab + config_resist_edge) - *y = ab - h + 1; - else if (ct >= pt && t < pt && t >= pt - config_resist_edge) - *y = pt; - else if (cb <= pb && b > pb && b < pb + config_resist_edge) - *y = pb - h + 1; - } + for (i = 0; i < screen_num_monitors; ++i) { + area = screen_area_monitor(c->desktop, i); + parea = screen_physical_area_monitor(i); + + if (!RECT_INTERSECTS_RECT(*parea, c->frame->area)) + continue; + + al = RECT_LEFT(*area); + at = RECT_TOP(*area); + ar = RECT_RIGHT(*area); + ab = RECT_BOTTOM(*area); + pl = RECT_LEFT(*parea); + pt = RECT_TOP(*parea); + pr = RECT_RIGHT(*parea); + pb = RECT_BOTTOM(*parea); + + if (cl >= al && l < al && l >= al - resist) + *x = al; + else if (cr <= ar && r > ar && r <= ar + resist) + *x = ar - w + 1; + else if (cl >= pl && l < pl && l >= pl - resist) + *x = pl; + else if (cr <= pr && r > pr && r <= pr + resist) + *x = pr - w + 1; + + if (ct >= at && t < at && t >= at - resist) + *y = at; + else if (cb <= ab && b > ab && b < ab + resist) + *y = ab - h + 1; + else if (ct >= pt && t < pt && t >= pt - resist) + *y = pt; + else if (cb <= pb && b > pb && b < pb + resist) + *y = pb - h + 1; } } -void resist_size_windows(ObClient *c, gint *w, gint *h, ObCorner corn) +void resist_size_windows(ObClient *c, gint resist, gint *w, gint *h, + ObCorner corn) { GList *it; ObClient *target; /* target */ @@ -184,6 +186,8 @@ void resist_size_windows(ObClient *c, gint *w, gint *h, ObCorner corn) gint incw, inch; ObClient *snapx = NULL, *snapy = NULL; + if (!resist) return; + incw = c->size_inc.width; inch = c->size_inc.height; @@ -192,79 +196,78 @@ void resist_size_windows(ObClient *c, gint *w, gint *h, ObCorner corn) t = RECT_TOP(c->frame->area); b = RECT_BOTTOM(c->frame->area); - if (config_resist_win) { - for (it = stacking_list; it; it = g_list_next(it)) { - if (!WINDOW_IS_CLIENT(it->data)) - continue; - target = it->data; - - /* don't snap to invisibles or ourself */ - if (!target->frame->visible || target == c) continue; - - /* don't snap to windows in layers beneath */ - if(target->layer < c->layer && !config_resist_layers_below) - continue; - - tl = RECT_LEFT(target->frame->area); - tr = RECT_RIGHT(target->frame->area); - tt = RECT_TOP(target->frame->area); - tb = RECT_BOTTOM(target->frame->area); - - if (snapx == NULL) { - /* horizontal snapping */ - if (t < tb && b > tt) { - switch (corn) { - case OB_CORNER_TOPLEFT: - case OB_CORNER_BOTTOMLEFT: - dlt = l; - drb = r + *w - c->frame->area.width; - if (r < tl && drb >= tl && - drb < tl + config_resist_win) - *w = tl - l, snapx = target; - break; - case OB_CORNER_TOPRIGHT: - case OB_CORNER_BOTTOMRIGHT: - dlt = l - *w + c->frame->area.width; - drb = r; - if (l > tr && dlt <= tr && - dlt > tr - config_resist_win) - *w = r - tr, snapx = target; - break; - } + for (it = stacking_list; it; it = g_list_next(it)) { + if (!WINDOW_IS_CLIENT(it->data)) + continue; + target = it->data; + + /* don't snap to invisibles or ourself */ + if (!target->frame->visible || target == c) continue; + + /* don't snap to windows in layers beneath */ + if(target->layer < c->layer && !config_resist_layers_below) + continue; + + tl = RECT_LEFT(target->frame->area); + tr = RECT_RIGHT(target->frame->area); + tt = RECT_TOP(target->frame->area); + tb = RECT_BOTTOM(target->frame->area); + + if (snapx == NULL) { + /* horizontal snapping */ + if (t < tb && b > tt) { + switch (corn) { + case OB_CORNER_TOPLEFT: + case OB_CORNER_BOTTOMLEFT: + dlt = l; + drb = r + *w - c->frame->area.width; + if (r < tl && drb >= tl && + drb < tl + resist) + *w = tl - l, snapx = target; + break; + case OB_CORNER_TOPRIGHT: + case OB_CORNER_BOTTOMRIGHT: + dlt = l - *w + c->frame->area.width; + drb = r; + if (l > tr && dlt <= tr && + dlt > tr - resist) + *w = r - tr, snapx = target; + break; } } + } - if (snapy == NULL) { - /* vertical snapping */ - if (l < tr && r > tl) { - switch (corn) { - case OB_CORNER_TOPLEFT: - case OB_CORNER_TOPRIGHT: - dlt = t; - drb = b + *h - c->frame->area.height; - if (b < tt && drb >= tt && - drb < tt + config_resist_win) - *h = tt - t, snapy = target; - break; - case OB_CORNER_BOTTOMLEFT: - case OB_CORNER_BOTTOMRIGHT: - dlt = t - *h + c->frame->area.height; - drb = b; - if (t > tb && dlt <= tb && - dlt > tb - config_resist_win) - *h = b - tb, snapy = target; - break; - } + if (snapy == NULL) { + /* vertical snapping */ + if (l < tr && r > tl) { + switch (corn) { + case OB_CORNER_TOPLEFT: + case OB_CORNER_TOPRIGHT: + dlt = t; + drb = b + *h - c->frame->area.height; + if (b < tt && drb >= tt && + drb < tt + resist) + *h = tt - t, snapy = target; + break; + case OB_CORNER_BOTTOMLEFT: + case OB_CORNER_BOTTOMRIGHT: + dlt = t - *h + c->frame->area.height; + drb = b; + if (t > tb && dlt <= tb && + dlt > tb - resist) + *h = b - tb, snapy = target; + break; } } - - /* snapped both ways */ - if (snapx && snapy) break; } + + /* snapped both ways */ + if (snapx && snapy) break; } } -void resist_size_monitors(ObClient *c, gint *w, gint *h, ObCorner corn) +void resist_size_monitors(ObClient *c, gint resist, gint *w, gint *h, + ObCorner corn) { gint l, t, r, b; /* my left, top, right and bottom sides */ gint dlt, drb; /* my destination left/top and right/bottom sides */ @@ -274,6 +277,8 @@ void resist_size_monitors(ObClient *c, gint *w, gint *h, ObCorner corn) gint incw, inch; guint i; + if (!resist) return; + l = RECT_LEFT(c->frame->area); r = RECT_RIGHT(c->frame->area); t = RECT_TOP(c->frame->area); @@ -299,50 +304,48 @@ void resist_size_monitors(ObClient *c, gint *w, gint *h, ObCorner corn) pr = RECT_RIGHT(*parea); pb = RECT_BOTTOM(*parea); - if (config_resist_edge) { - /* horizontal snapping */ - switch (corn) { - case OB_CORNER_TOPLEFT: - case OB_CORNER_BOTTOMLEFT: - dlt = l; - drb = r + *w - c->frame->area.width; - if (r <= ar && drb > ar && drb <= ar + config_resist_edge) - *w = ar - l + 1; - else if (r <= pr && drb > pr && drb <= pr + config_resist_edge) - *w = pr - l + 1; - break; - case OB_CORNER_TOPRIGHT: - case OB_CORNER_BOTTOMRIGHT: - dlt = l - *w + c->frame->area.width; - drb = r; - if (l >= al && dlt < al && dlt >= al - config_resist_edge) - *w = r - al + 1; - else if (l >= pl && dlt < pl && dlt >= pl - config_resist_edge) - *w = r - pl + 1; - break; - } + /* horizontal snapping */ + switch (corn) { + case OB_CORNER_TOPLEFT: + case OB_CORNER_BOTTOMLEFT: + dlt = l; + drb = r + *w - c->frame->area.width; + if (r <= ar && drb > ar && drb <= ar + resist) + *w = ar - l + 1; + else if (r <= pr && drb > pr && drb <= pr + resist) + *w = pr - l + 1; + break; + case OB_CORNER_TOPRIGHT: + case OB_CORNER_BOTTOMRIGHT: + dlt = l - *w + c->frame->area.width; + drb = r; + if (l >= al && dlt < al && dlt >= al - resist) + *w = r - al + 1; + else if (l >= pl && dlt < pl && dlt >= pl - resist) + *w = r - pl + 1; + break; + } - /* vertical snapping */ - switch (corn) { - case OB_CORNER_TOPLEFT: - case OB_CORNER_TOPRIGHT: - dlt = t; - drb = b + *h - c->frame->area.height; - if (b <= ab && drb > ab && drb <= ab + config_resist_edge) - *h = ab - t + 1; - else if (b <= pb && drb > pb && drb <= pb + config_resist_edge) - *h = pb - t + 1; - break; - case OB_CORNER_BOTTOMLEFT: - case OB_CORNER_BOTTOMRIGHT: - dlt = t - *h + c->frame->area.height; - drb = b; - if (t >= at && dlt < at && dlt >= at - config_resist_edge) - *h = b - at + 1; - else if (t >= pt && dlt < pt && dlt >= pt - config_resist_edge) - *h = b - pt + 1; - break; - } + /* vertical snapping */ + switch (corn) { + case OB_CORNER_TOPLEFT: + case OB_CORNER_TOPRIGHT: + dlt = t; + drb = b + *h - c->frame->area.height; + if (b <= ab && drb > ab && drb <= ab + resist) + *h = ab - t + 1; + else if (b <= pb && drb > pb && drb <= pb + resist) + *h = pb - t + 1; + break; + case OB_CORNER_BOTTOMLEFT: + case OB_CORNER_BOTTOMRIGHT: + dlt = t - *h + c->frame->area.height; + drb = b; + if (t >= at && dlt < at && dlt >= at - resist) + *h = b - at + 1; + else if (t >= pt && dlt < pt && dlt >= pt - resist) + *h = b - pt + 1; + break; } } } diff --git a/openbox/resist.h b/openbox/resist.h index b961bbeb..7c3ed3c3 100644 --- a/openbox/resist.h +++ b/openbox/resist.h @@ -23,9 +23,11 @@ struct _ObClient; #include -void resist_move_windows(struct _ObClient *c, gint *x, gint *y); -void resist_move_monitors(struct _ObClient *c, gint *x, gint *y); -void resist_size_windows(struct _ObClient *c, gint *w, gint *h, ObCorner corn); -void resist_size_monitors(struct _ObClient *c, gint *w, gint *h,ObCorner corn); +void resist_move_windows(struct _ObClient *c, gint resist, gint *x, gint *y); +void resist_move_monitors(struct _ObClient *c, gint resist, gint *x, gint *y); +void resist_size_windows(struct _ObClient *c, gint resist, gint *w, gint *h, + ObCorner corn); +void resist_size_monitors(struct _ObClient *c, gint resist, gint *w, gint *h, + ObCorner corn); #endif diff --git a/openbox/screen.c b/openbox/screen.c index d48d0dda..9265c73b 100644 --- a/openbox/screen.c +++ b/openbox/screen.c @@ -273,6 +273,7 @@ gboolean screen_annex(const gchar *program_name) supported[i++] = prop_atoms.net_moveresize_window; supported[i++] = prop_atoms.net_wm_moveresize; supported[i++] = prop_atoms.net_wm_user_time; + supported[i++] = prop_atoms.net_wm_user_time_window; supported[i++] = prop_atoms.net_frame_extents; supported[i++] = prop_atoms.net_startup_id; #ifdef SYNC @@ -647,20 +648,12 @@ void screen_desktop_popup(guint d, gboolean show) guint screen_cycle_desktop(ObDirection dir, gboolean wrap, gboolean linear, gboolean dialog, gboolean done, gboolean cancel) { - static gboolean first = TRUE; - static guint origd, d; - guint r, c; - - if (cancel) { - d = origd; - goto done_cycle; - } else if (done && dialog) { - goto done_cycle; - } - if (first) { - first = FALSE; - d = origd = screen_desktop; - } + guint d, r, c; + + d = screen_desktop; + + if ((cancel || done) && dialog) + goto show_cycle_dialog; get_row_col(d, &r, &c); @@ -773,16 +766,10 @@ guint screen_cycle_desktop(ObDirection dir, gboolean wrap, gboolean linear, } show_cycle_dialog: - if (dialog) { + if (dialog && !cancel && !done) { screen_desktop_popup(d, TRUE); - return d; - } - -done_cycle: - first = TRUE; - - screen_desktop_popup(0, FALSE); - + } else + screen_desktop_popup(0, FALSE); return d; } @@ -1267,7 +1254,16 @@ gboolean screen_pointer_pos(gint *x, gint *y) Window w; gint i; guint u; - - return !!XQueryPointer(ob_display, RootWindow(ob_display, ob_screen), - &w, &w, x, y, &i, &i, &u); + gboolean ret; + + ret = !!XQueryPointer(ob_display, RootWindow(ob_display, ob_screen), + &w, &w, x, y, &i, &i, &u); + if (!ret) { + for (i = 0; i < ScreenCount(ob_display); ++i) + if (i != ob_screen) + if (XQueryPointer(ob_display, RootWindow(ob_display, i), + &w, &w, x, y, &i, &i, &u)) + break; + } + return ret; } diff --git a/openbox/screen.h b/openbox/screen.h index ccaa4f57..a84170f8 100644 --- a/openbox/screen.h +++ b/openbox/screen.h @@ -107,6 +107,8 @@ guint screen_find_monitor(Rect *search); gotta call it to let it know it should change. */ void screen_set_root_cursor(); +/*! Gives back the pointer's position in x and y. Returns TRUE if the pointer + is on this screen and FALSE if it is on another screen. */ gboolean screen_pointer_pos(gint *x, gint *y); #endif diff --git a/openbox/window.c b/openbox/window.c index 7b3428bd..19b39c09 100644 --- a/openbox/window.c +++ b/openbox/window.c @@ -25,11 +25,15 @@ GHashTable *window_map; +static guint window_hash(Window *w) { return *w; } +static gboolean window_comp(Window *w1, Window *w2) { return *w1 == *w2; } + void window_startup(gboolean reconfig) { if (reconfig) return; - window_map = g_hash_table_new(g_int_hash, g_int_equal); + window_map = g_hash_table_new((GHashFunc)window_hash, + (GEqualFunc)window_comp); } void window_shutdown(gboolean reconfig) -- 2.39.2