#include "mainloop.h"
#include "framerender.h"
#include "focus.h"
+#include "focus_cycle.h"
#include "moveresize.h"
#include "group.h"
#include "stacking.h"
}
} else if (msgtype == prop_atoms.net_number_of_desktops) {
guint d = e->xclient.data.l[0];
- if (d > 0)
+ if (d > 0 && d <= 1000)
screen_set_num_desktops(d);
} else if (msgtype == prop_atoms.net_showing_desktop) {
screen_show_desktop(e->xclient.data.l[0] != 0, NULL);
{
/* use where the press occured */
con = frame_context(client, e->xbutton.window, px, py);
- con = mouse_button_frame_context(con, e->xbutton.button);
+ con = mouse_button_frame_context(con, e->xbutton.button,
+ e->xbutton.state);
if (e->type == ButtonRelease && e->xbutton.button == pb)
pb = 0, px = py = -1;
e->xmotion.x, e->xmotion.y);
switch (con) {
case OB_FRAME_CONTEXT_TITLEBAR:
+ case OB_FRAME_CONTEXT_TLCORNER:
+ case OB_FRAME_CONTEXT_TRCORNER:
/* we've left the button area inside the titlebar */
if (client->frame->max_hover || client->frame->desk_hover ||
client->frame->shade_hover || client->frame->iconify_hover ||
con = frame_context(client, e->xcrossing.window,
e->xcrossing.x, e->xcrossing.y);
switch (con) {
+ case OB_FRAME_CONTEXT_TITLEBAR:
+ case OB_FRAME_CONTEXT_TLCORNER:
+ case OB_FRAME_CONTEXT_TRCORNER:
+ /* we've left the button area inside the titlebar */
+ if (client->frame->max_hover || client->frame->desk_hover ||
+ client->frame->shade_hover || client->frame->iconify_hover ||
+ client->frame->close_hover)
+ {
+ client->frame->max_hover = FALSE;
+ client->frame->desk_hover = FALSE;
+ client->frame->shade_hover = FALSE;
+ client->frame->iconify_hover = FALSE;
+ client->frame->close_hover = FALSE;
+ frame_adjust_state(client->frame);
+ }
+ break;
case OB_FRAME_CONTEXT_MAXIMIZE:
client->frame->max_hover = FALSE;
frame_adjust_state(client->frame);
*/
gint x, y, w, h;
+ gboolean move = FALSE;
+ gboolean resize = FALSE;
- /* if nothing is changed, then a configurenotify is needed */
- gboolean config = TRUE;
-
- x = client->area.x;
- y = client->area.y;
- w = client->area.width;
- h = client->area.height;
+ /* get the current area */
+ RECT_TO_DIMS(client->area, x, y, w, h);
ob_debug("ConfigureRequest desktop %d wmstate %d visibile %d\n",
screen_desktop, client->wmstate, client->frame->visible);
if (e->xconfigurerequest.value_mask & CWBorderWidth)
if (client->border_width != e->xconfigurerequest.border_width) {
client->border_width = e->xconfigurerequest.border_width;
- /* if only the border width is changing, then it's not needed*/
- config = FALSE;
+
+ /* if the border width is changing then that is the same
+ as requesting a resize, but we don't actually change
+ the client's border, so it will change their root
+ coordiantes (since they include the border width) and
+ we need to a notify then */
+ move = TRUE;
}
stacking_restack_request(client, sibling,
e->xconfigurerequest.detail, TRUE);
- /* if a stacking change is requested then it is needed */
- config = TRUE;
- }
-
- /* don't allow clients to move shaded windows (fvwm does this) */
- if (client->shaded && (e->xconfigurerequest.value_mask & CWX ||
- e->xconfigurerequest.value_mask & CWY))
- {
- e->xconfigurerequest.value_mask &= ~CWX;
- e->xconfigurerequest.value_mask &= ~CWY;
-
- /* if the client tried to move and we aren't letting it then a
- synthetic event is needed */
- config = TRUE;
+ /* if a stacking change moves the window without resizing */
+ move = TRUE;
}
if (e->xconfigurerequest.value_mask & CWX ||
e->xconfigurerequest.value_mask & CWWidth ||
e->xconfigurerequest.value_mask & CWHeight)
{
- if (e->xconfigurerequest.value_mask & CWX)
- x = e->xconfigurerequest.x;
- if (e->xconfigurerequest.value_mask & CWY)
- y = e->xconfigurerequest.y;
- if (e->xconfigurerequest.value_mask & CWWidth)
+ if (e->xconfigurerequest.value_mask & CWX) {
+ /* don't allow clients to move shaded windows (fvwm does this)
+ */
+ if (!client->shaded)
+ x = e->xconfigurerequest.x;
+ move = TRUE;
+ }
+ if (e->xconfigurerequest.value_mask & CWY) {
+ /* don't allow clients to move shaded windows (fvwm does this)
+ */
+ if (!client->shaded)
+ y = e->xconfigurerequest.y;
+ move = TRUE;
+ }
+
+ if (e->xconfigurerequest.value_mask & CWWidth) {
w = e->xconfigurerequest.width;
- if (e->xconfigurerequest.value_mask & CWHeight)
+ resize = TRUE;
+
+ /* if x was not given, then use gravity to figure out the new
+ x. the reference point should not be moved */
+ if (!(e->xconfigurerequest.value_mask & CWX))
+ client_gravity_resize_w(client, &x, client->area.width, w);
+ }
+ if (e->xconfigurerequest.value_mask & CWHeight) {
h = e->xconfigurerequest.height;
+ resize = TRUE;
- /* if a new position or size is requested, then a configure is
- needed */
- config = TRUE;
+ /* if y was not given, then use gravity to figure out the new
+ y. the reference point should not be moved */
+ if (!(e->xconfigurerequest.value_mask & CWY))
+ client_gravity_resize_h(client, &y, client->area.height,h);
+ }
}
- ob_debug("ConfigureRequest x(%d) %d y(%d) %d w(%d) %d h(%d) %d\n",
+ ob_debug("ConfigureRequest x(%d) %d y(%d) %d w(%d) %d h(%d) %d "
+ "move %d resize %d\n",
e->xconfigurerequest.value_mask & CWX, x,
e->xconfigurerequest.value_mask & CWY, y,
e->xconfigurerequest.value_mask & CWWidth, w,
- e->xconfigurerequest.value_mask & CWHeight, h);
+ e->xconfigurerequest.value_mask & CWHeight, h,
+ move, resize);
/* check for broken apps moving to their root position
desktop. eg. open amarok window on desktop 1, switch to desktop
2, click amarok tray icon. it will move by its decoration size.
*/
- if (x != client->area.x &&
+ if (move && !resize &&
+ x != client->area.x &&
x == (client->frame->area.x + client->frame->size.left -
(gint)client->border_width) &&
y != client->area.y &&
/* don't move it */
x = client->area.x;
y = client->area.y;
+
+ /* they still requested a move, so don't change whether a
+ notify is sent or not */
}
- if (config) {
+ if (move || resize) {
+ gint lw,lh;
+
client_find_onscreen(client, &x, &y, w, h, FALSE);
- client_configure(client, x, y, w, h, FALSE, TRUE);
+ client_try_configure(client, &x, &y, &w, &h, &lw, &lh, FALSE);
+ /* if they requested something that moves the window, or if
+ the window is actually being changed then configure it and
+ send a configure notify to them */
+ if (move || !RECT_EQUAL_DIMS(client->area, x, y, w, h)) {
+ ob_debug("Doing configure\n");
+ client_configure(client, x, y, w, h, FALSE, TRUE);
+ }
/* ignore enter events caused by these like ob actions do */
event_ignore_all_queued_enters();
(e->xclient.data.l[0] == 1 ? "application" :
(e->xclient.data.l[0] == 2 ? "user" : "INVALID"))));
/* XXX make use of data.l[2] !? */
- event_curtime = e->xclient.data.l[1];
- if (event_curtime == 0)
+ if (e->xclient.data.l[0] == 1 || e->xclient.data.l[0] == 2) {
+ event_curtime = e->xclient.data.l[1];
+ if (event_curtime == 0)
+ ob_debug_type(OB_DEBUG_APP_BUGS,
+ "_NET_ACTIVE_WINDOW message for window %s is"
+ " missing a timestamp\n", client->title);
+ } else
ob_debug_type(OB_DEBUG_APP_BUGS,
"_NET_ACTIVE_WINDOW message for window %s is "
- "missing a timestamp\n", client->title);
+ "missing source indication\n");
client_activate(client, FALSE,
(e->xclient.data.l[0] == 0 ||
e->xclient.data.l[0] == 2));
prop_atoms.net_wm_moveresize_cancel)
moveresize_end(TRUE);
} else if (msgtype == prop_atoms.net_moveresize_window) {
- gint grav, x, y, w, h;
+ gint ograv, x, y, w, h;
+
+ ograv = client->gravity;
if (e->xclient.data.l[0] & 0xff)
- grav = e->xclient.data.l[0] & 0xff;
- else
- grav = client->gravity;
+ client->gravity = e->xclient.data.l[0] & 0xff;
if (e->xclient.data.l[0] & 1 << 8)
x = e->xclient.data.l[1];
y = e->xclient.data.l[2];
else
y = client->area.y;
- if (e->xclient.data.l[0] & 1 << 10)
+
+ if (e->xclient.data.l[0] & 1 << 10) {
w = e->xclient.data.l[3];
+
+ /* if x was not given, then use gravity to figure out the new
+ x. the reference point should not be moved */
+ if (!(e->xclient.data.l[0] & 1 << 8))
+ client_gravity_resize_w(client, &x, client->area.width, w);
+ }
else
w = client->area.width;
- if (e->xclient.data.l[0] & 1 << 11)
+
+ if (e->xclient.data.l[0] & 1 << 11) {
h = e->xclient.data.l[4];
+
+ /* if y was not given, then use gravity to figure out the new
+ y. the reference point should not be moved */
+ if (!(e->xclient.data.l[0] & 1 << 9))
+ client_gravity_resize_h(client, &y, client->area.height,h);
+ }
else
h = client->area.height;
- ob_debug("MOVERESIZE x %d %d y %d %d\n",
+ ob_debug("MOVERESIZE x %d %d y %d %d (gravity %d)\n",
e->xclient.data.l[0] & 1 << 8, x,
- e->xclient.data.l[0] & 1 << 9, y);
- client_convert_gravity(client, grav, &x, &y, w, h);
+ e->xclient.data.l[0] & 1 << 9, y,
+ client->gravity);
+
client_find_onscreen(client, &x, &y, w, h, FALSE);
client_configure(client, x, y, w, h, FALSE, TRUE);
+ client->gravity = ograv;
+
/* ignore enter events caused by these like ob actions do */
event_ignore_all_queued_enters();
} else if (msgtype == prop_atoms.net_restack_window) {
} else {
ObClient *sibling = NULL;
if (e->xclient.data.l[1]) {
- ObWindow *win = g_hash_table_lookup(window_map,
- &e->xclient.data.l[1]);
+ ObWindow *win = g_hash_table_lookup
+ (window_map, &e->xclient.data.l[1]);
if (WINDOW_IS_CLIENT(win) &&
WINDOW_AS_CLIENT(win) != client)
{
ret = FALSE;
else if (keycode == ob_keycode(OB_KEY_ESCAPE) && state == 0) {
- /* Escape closes the active menu */
- menu_frame_hide(frame);
+ /* Escape goes to the parent menu or closes the last one */
+ if (frame->parent)
+ menu_frame_select(frame, NULL, TRUE);
+ else
+ menu_frame_hide_all();
}
else if (keycode == ob_keycode(OB_KEY_RETURN) && (state == 0 ||
}
break;
case LeaveNotify:
+ /*ignore leaves when we're already in the window */
+ if (ev->xcrossing.detail == NotifyInferior)
+ break;
+
if ((e = g_hash_table_lookup(menu_frame_map, &ev->xcrossing.window)) &&
(f = find_active_menu()) && f->selected == e &&
e->entry->type != OB_MENU_ENTRY_TYPE_SUBMENU)