X-Git-Url: https://git.brokenzipper.com/gitweb?a=blobdiff_plain;f=openbox%2Fevent.c;h=271114a27d0907f77a8aee42533fe2dd11add46d;hb=c2c84c3f5ed75561d7d6502f787ab06bc7d984d2;hp=babb5197c193ee0316f7403ad303dc2d107b2683;hpb=851555348ec39a01a0e150d2e12b71212b8d338b;p=chaz%2Fopenbox diff --git a/openbox/event.c b/openbox/event.c index babb5197..271114a2 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -568,8 +568,32 @@ static void event_process(const XEvent *ec, gpointer data) event_handle_root(e); else if (e->type == MapRequest) client_manage(window); + else if (e->type == ClientMessage) { + /* This is for _NET_WM_REQUEST_FRAME_EXTENTS messages. They come for + windows that are not managed yet. */ + if (e->xclient.message_type == prop_atoms.net_request_frame_extents) { + /* Pretend to manage the client, getting information used to + determine its decorations */ + ObClient *c = client_fake_manage(e->xclient.window); + gulong vals[4]; + + /* adjust the decorations so we know the sizes */ + frame_adjust_area(c->frame, FALSE, TRUE, TRUE); + + /* set the frame extents on the window */ + vals[0] = c->frame->size.left; + vals[1] = c->frame->size.right; + vals[2] = c->frame->size.top; + vals[3] = c->frame->size.bottom; + PROP_SETA32(e->xclient.window, net_frame_extents, + cardinal, vals, 4); + + /* Free the pretend client */ + client_fake_unmanage(c); + } + } else if (e->type == ConfigureRequest) { - /* unhandled configure requests must be used to configure the + /* unhandled config5Aure requests must be used to configure the window directly */ XWindowChanges xwc; @@ -705,9 +729,17 @@ static void event_handle_client(ObClient *client, XEvent *e) XEvent ce; Atom msgtype; ObFrameContext con; + static gint px = -1, py = -1; + static guint pb = 0; switch (e->type) { case ButtonPress: + /* save where the press occured for the first button pressed */ + if (!pb) { + pb = e->xbutton.button; + px = e->xbutton.x; + py = e->xbutton.y; + } case ButtonRelease: /* Wheel buttons don't draw because they are an instant click, so it is a waste of resources to go drawing it. @@ -719,8 +751,13 @@ static void event_handle_client(ObClient *client, XEvent *e) !keyboard_interactively_grabbed() && !menu_frame_visible) { - con = frame_context(client, e->xbutton.window); + /* use where the press occured */ + con = frame_context(client, e->xbutton.window, px, py); con = mouse_button_frame_context(con, e->xbutton.button); + + if (e->type == ButtonRelease && e->xbutton.button == pb) + pb = 0, px = py = -1; + switch (con) { case OB_FRAME_CONTEXT_MAXIMIZE: client->frame->max_press = (e->type == ButtonPress); @@ -748,8 +785,61 @@ static void event_handle_client(ObClient *client, XEvent *e) } } break; + case MotionNotify: + con = frame_context(client, e->xmotion.window, + e->xmotion.x, e->xmotion.y); + switch (con) { + case OB_FRAME_CONTEXT_TITLEBAR: + /* 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: + if (!client->frame->max_hover) { + client->frame->max_hover = TRUE; + frame_adjust_state(client->frame); + } + break; + case OB_FRAME_CONTEXT_ALLDESKTOPS: + if (!client->frame->desk_hover) { + client->frame->desk_hover = TRUE; + frame_adjust_state(client->frame); + } + break; + case OB_FRAME_CONTEXT_SHADE: + if (!client->frame->shade_hover) { + client->frame->shade_hover = TRUE; + frame_adjust_state(client->frame); + } + break; + case OB_FRAME_CONTEXT_ICONIFY: + if (!client->frame->iconify_hover) { + client->frame->iconify_hover = TRUE; + frame_adjust_state(client->frame); + } + break; + case OB_FRAME_CONTEXT_CLOSE: + if (!client->frame->close_hover) { + client->frame->close_hover = TRUE; + frame_adjust_state(client->frame); + } + break; + default: + break; + } + break; case LeaveNotify: - con = frame_context(client, e->xcrossing.window); + con = frame_context(client, e->xcrossing.window, + e->xcrossing.x, e->xcrossing.y); switch (con) { case OB_FRAME_CONTEXT_MAXIMIZE: client->frame->max_hover = FALSE; @@ -809,7 +899,8 @@ static void event_handle_client(ObClient *client, XEvent *e) nofocus = TRUE; } - con = frame_context(client, e->xcrossing.window); + con = frame_context(client, e->xcrossing.window, + e->xcrossing.x, e->xcrossing.y); switch (con) { case OB_FRAME_CONTEXT_MAXIMIZE: client->frame->max_hover = TRUE; @@ -928,22 +1019,19 @@ static void event_handle_client(ObClient *client, XEvent *e) } if (e->xconfigurerequest.value_mask & CWStackMode) { - switch (e->xconfigurerequest.detail) { - case Below: - case BottomIf: - /* Apps are so rude. And this is totally disconnected from - activation/focus. Bleh. */ - /*client_lower(client);*/ - break; - - case Above: - case TopIf: - default: - /* Apps are so rude. And this is totally disconnected from - activation/focus. Bleh. */ - /*client_raise(client);*/ - break; + ObClient *sibling = NULL; + + /* get the sibling */ + if (e->xconfigurerequest.value_mask & CWSibling) { + ObWindow *win; + win = g_hash_table_lookup(window_map, + &e->xconfigurerequest.above); + if (WINDOW_IS_CLIENT(win) && WINDOW_AS_CLIENT(win) != client) + sibling = WINDOW_AS_CLIENT(win); } + + stacking_restack_request(client, sibling, + e->xconfigurerequest.detail); } break; case UnmapNotify: @@ -1120,6 +1208,41 @@ static void event_handle_client(ObClient *client, XEvent *e) client_convert_gravity(client, grav, &x, &y, w, h); client_find_onscreen(client, &x, &y, w, h, FALSE); client_configure(client, x, y, w, h, FALSE, TRUE); + } else if (msgtype == prop_atoms.net_restack_window) { + if (e->xclient.data.l[0] != 2) { + ob_debug_type(OB_DEBUG_APP_BUGS, + "_NET_RESTACK_WINDOW sent for window %s with " + "invalid source indication %ld\n", + client->title, e->xclient.data.l[0]); + } else { + ObClient *sibling = NULL; + if (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) + { + sibling = WINDOW_AS_CLIENT(win); + } + if (sibling == NULL) + ob_debug_type(OB_DEBUG_APP_BUGS, + "_NET_RESTACK_WINDOW sent for window %s " + "with invalid sibling 0x%x\n", + client->title, e->xclient.data.l[1]); + } + if (e->xclient.data.l[2] == Below || + e->xclient.data.l[2] == BottomIf || + e->xclient.data.l[2] == Above || + e->xclient.data.l[2] == TopIf || + e->xclient.data.l[2] == Opposite) + { + stacking_restack_request(client, sibling, + e->xclient.data.l[2]); + } + ob_debug_type(OB_DEBUG_APP_BUGS, "_NET_RESTACK_WINDOW sent " + "for window %s with invalid detail 0d\n", + client->title, e->xclient.data.l[2]); + } } break; case PropertyNotify: @@ -1167,7 +1290,7 @@ static void event_handle_client(ObClient *client, XEvent *e) client_update_wmhints(client); } else if (msgtype == XA_WM_TRANSIENT_FOR) { client_update_transient_for(client); - client_get_type(client); + client_get_type_and_transientness(client); /* type may have changed, so update the layer */ client_calc_layer(client); client_setup_decor_and_functions(client); @@ -1510,7 +1633,7 @@ static gboolean focus_delay_func(gpointer data) event_curtime = d->time; if (focus_client != d->client) { if (client_focus(d->client) && config_focus_raise) - client_raise(d->client); + stacking_raise(CLIENT_AS_WINDOW(d->client)); } event_curtime = old; return FALSE; /* no repeat */