X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fevent.c;h=7596fe3e4175b91548b9dcd862ae2c706a8d3acf;hb=28df6162a9fbca4544e8f384d3fdae70870f531a;hp=45ae101e7f5a925170efb7fb7829d5509980d15b;hpb=567fd15eebdd44e50cef140419dbf7a336708109;p=chaz%2Fopenbox diff --git a/openbox/event.c b/openbox/event.c index 45ae101e..7596fe3e 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -56,9 +56,6 @@ #ifdef HAVE_UNISTD_H # include /* for usleep() */ #endif -#ifdef XKB -# include -#endif #ifdef USE_SM #include @@ -260,34 +257,14 @@ static void event_set_curtime(XEvent *e) static void event_hack_mods(XEvent *e) { -#ifdef XKB - XkbStateRec xkb_state; -#endif - switch (e->type) { case ButtonPress: case ButtonRelease: e->xbutton.state = obt_keyboard_only_modmasks(e->xbutton.state); break; case KeyPress: - e->xkey.state = obt_keyboard_only_modmasks(e->xkey.state); break; case KeyRelease: -#ifdef XKB - /* If XKB is present, then the modifiers are all strange from its - magic. Our X core protocol stuff won't work, so we use this to - find what the modifier state is instead. */ - if (XkbGetState(obt_display, XkbUseCoreKbd, &xkb_state) == Success) - e->xkey.state = - obt_keyboard_only_modmasks(xkb_state.compat_state); - else -#endif - { - e->xkey.state = obt_keyboard_only_modmasks(e->xkey.state); - /* remove from the state the mask of the modifier key being - released, if it is a modifier key being released that is */ - e->xkey.state &= ~obt_keyboard_keycode_to_modmask(e->xkey.keycode); - } break; case MotionNotify: e->xmotion.state = obt_keyboard_only_modmasks(e->xmotion.state); @@ -719,22 +696,27 @@ static void event_process(const XEvent *ec, gpointer data) #endif if (e->type == ButtonPress || e->type == ButtonRelease) { + ObWindow *w; + static guint pressed = 0; + static Window pressed_win = None; + /* If the button press was on some non-root window, or was physically - on the root window, then process it */ + on the root window... */ if (window != obt_root(ob_screen) || - e->xbutton.subwindow == None) + e->xbutton.subwindow == None || + /* ...or if it is related to the last button press we handled... */ + pressed == e->xbutton.button || + /* ...or it if it was physically on an openbox + internal window... */ + ((w = window_find(e->xbutton.subwindow)) && + WINDOW_IS_INTERNAL(w))) + /* ...then process the event, otherwise ignore it */ { used = event_handle_user_input(client, e); - } - /* Otherwise only process it if it was physically on an openbox - internal window */ - else { - ObWindow *w; - if ((w = window_find(e->xbutton.subwindow)) && - WINDOW_IS_INTERNAL(w)) - { - used = event_handle_user_input(client, e); + if (e->type == ButtonPress) { + pressed = e->xbutton.button; + pressed_win = e->xbutton.subwindow; } } } @@ -829,7 +811,7 @@ void event_enter_client(ObClient *client) obt_main_loop_timeout_remove(ob_main_loop, focus_delay_func); - data = g_new(ObFocusDelayData, 1); + data = g_slice_new(ObFocusDelayData); data->client = client; data->time = event_curtime; data->serial = event_curserial; @@ -864,7 +846,7 @@ void event_leave_client(ObClient *client) obt_main_loop_timeout_remove(ob_main_loop, unfocus_delay_func); - data = g_new(ObFocusDelayData, 1); + data = g_slice_new(ObFocusDelayData); data->client = client; data->time = event_curtime; data->serial = event_curserial; @@ -1265,6 +1247,49 @@ static void event_handle_client(ObClient *client, XEvent *e) notify is sent or not */ } + /* check for broken apps (java swing) moving to 0,0 when there is a + strut there. + + XXX remove this some day...that would be nice. but really unexpected + from Sun Microsystems. + */ + g_print("x %d y %d grav %d %d\n", x, y, client->gravity, NorthWestGravity); + if (x == 0 && y == 0 && client->gravity == NorthWestGravity) { + const Rect to = { x, y, w, h }; + Rect const *monitor, *allmonitors; + monitor = screen_physical_area_monitor(client_monitor(client)); + allmonitors = screen_physical_area_all_monitors(); + + /* oldschool fullscreen windows are allowed */ + if (!(client->decorations == 0 && + (RECT_EQUAL(to, *monitor) || + RECT_EQUAL(to, *allmonitors)))) + { + Rect *r; + + r = screen_area(client->desktop, SCREEN_AREA_ALL_MONITORS, + NULL); + if (r->x || r->y) { + /* move the window only to the corner outside struts */ + x = r->x; + y = r->y; + + ob_debug_type(OB_DEBUG_APP_BUGS, + "Application %s is trying to move via " + "ConfigureRequest to 0,0 using " + "NorthWestGravity, while there is a " + "strut there. " + "Moving buggy app from (0,0) to (%d,%d)", + client->title, r->x, r->y); + } + + g_slice_free(Rect, r); + + /* they still requested a move, so don't change whether a + notify is sent or not */ + } + } + { gint lw, lh; @@ -1375,11 +1400,23 @@ static void event_handle_client(ObClient *client, XEvent *e) (e->xclient.data.l[0] == 2 ? "user" : "INVALID")))); /* XXX make use of data.l[2] !? */ if (e->xclient.data.l[0] == 1 || e->xclient.data.l[0] == 2) { - event_curtime = e->xclient.data.l[1]; + /* we can not trust the timestamp from applications. + e.g. chromium passes a very old timestamp. openbox thinks + the window will get focus and calls XSetInputFocus with the + (old) timestamp, which doesn't end up moving focus at all. + but the window is raised, not hilited, etc, as if it was + really going to get focus. + + so do not use this timestamp in event_curtime, as this would + be used in XSetInputFocus. + */ + /*event_curtime = e->xclient.data.l[1];*/ if (e->xclient.data.l[1] == 0) ob_debug_type(OB_DEBUG_APP_BUGS, "_NET_ACTIVE_WINDOW message for window %s is" " missing a timestamp", client->title); + + event_curtime = event_get_server_time(); } else ob_debug_type(OB_DEBUG_APP_BUGS, "_NET_ACTIVE_WINDOW message for window %s is " @@ -1781,28 +1818,33 @@ static gboolean event_handle_menu_input(XEvent *ev) menu_frame_select(e->frame, e, FALSE); } else if (ev->type == KeyPress || ev->type == KeyRelease) { - guint keycode, state; - gunichar unikey; + guint mods; ObMenuFrame *frame; - keycode = ev->xkey.keycode; - state = ev->xkey.state; - unikey = obt_keyboard_keycode_to_unichar(keycode); + /* get the modifiers */ + mods = obt_keyboard_only_modmasks(ev->xkey.state); frame = find_active_or_last_menu(); if (frame == NULL) g_assert_not_reached(); /* there is no active menu */ /* Allow control while going thru the menu */ - else if (ev->type == KeyPress && (state & ~ControlMask) == 0) { + else if (ev->type == KeyPress && (mods & ~ControlMask) == 0) { + gunichar unikey; + KeySym sym; + frame->got_press = TRUE; + frame->press_keycode = ev->xkey.keycode; + frame->press_doexec = FALSE; - if (ob_keycode_match(keycode, OB_KEY_ESCAPE)) { + sym = obt_keyboard_keypress_to_keysym(ev); + + if (sym == XK_Escape) { menu_frame_hide_all(); ret = TRUE; } - else if (ob_keycode_match(keycode, OB_KEY_LEFT)) { + else if (sym == XK_Left) { /* Left goes to the parent menu */ if (frame->parent) { /* remove focus from the child */ @@ -1814,7 +1856,7 @@ static gboolean event_handle_menu_input(XEvent *ev) ret = TRUE; } - else if (ob_keycode_match(keycode, OB_KEY_RIGHT)) { + else if (sym == XK_Right) { /* Right goes to the selected submenu */ if (frame->selected->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU) { @@ -1825,47 +1867,37 @@ static gboolean event_handle_menu_input(XEvent *ev) ret = TRUE; } - else if (ob_keycode_match(keycode, OB_KEY_UP)) { + else if (sym == XK_Up) { menu_frame_select_previous(frame); ret = TRUE; } - else if (ob_keycode_match(keycode, OB_KEY_DOWN)) { + else if (sym == XK_Down) { menu_frame_select_next(frame); ret = TRUE; } - else if (ob_keycode_match(keycode, OB_KEY_HOME)) { + else if (sym == XK_Home) { menu_frame_select_first(frame); ret = TRUE; } - else if (ob_keycode_match(keycode, OB_KEY_END)) { + else if (sym == XK_End) { menu_frame_select_last(frame); ret = TRUE; } - } - - /* Use KeyRelease events for running things so that the key release - doesn't get sent to the focused application. - - Allow ControlMask only, and don't bother if the menu is empty */ - else if (ev->type == KeyRelease && (state & ~ControlMask) == 0 && - frame->entries && frame->got_press) - { - if (ob_keycode_match(keycode, OB_KEY_RETURN)) { - /* Enter runs the active item or goes into the submenu. - Control-Enter runs it without closing the menu. */ - if (frame->child) - menu_frame_select_next(frame->child); - else if (frame->selected) - menu_entry_frame_execute(frame->selected, state); + else if (sym == XK_Return) { + frame->press_doexec = TRUE; ret = TRUE; } /* keyboard accelerator shortcuts. (if it was a valid key) */ - else if (unikey != 0) { + else if (frame->entries && + (unikey = + obt_keyboard_keypress_to_unichar(menu_frame_ic(frame), + ev))) + { GList *start; GList *it; ObMenuEntryFrame *found = NULL; @@ -1903,23 +1935,30 @@ static gboolean event_handle_menu_input(XEvent *ev) } while (it != start); if (found) { - if (found->entry->type == OB_MENU_ENTRY_TYPE_NORMAL && - num_found == 1) - { - menu_frame_select(frame, found, TRUE); - usleep(50000); /* highlight the item for a short bit so - the user can see what happened */ - menu_entry_frame_execute(found, state); - } else { - menu_frame_select(frame, found, TRUE); - if (num_found == 1) - menu_frame_select_next(frame->child); - } + menu_frame_select(frame, found, TRUE); + if (num_found == 1) + frame->press_doexec = TRUE; ret = TRUE; } } } + + /* Use KeyRelease events for running things so that the key release + doesn't get sent to the focused application. + + Allow ControlMask only, and don't bother if the menu is empty */ + else if (ev->type == KeyRelease && (mods & ~ControlMask) == 0) { + if (frame->press_keycode == ev->xkey.keycode && + frame->got_press && + frame->press_doexec) + { + if (frame->child) + menu_frame_select_next(frame->child); + else if (frame->selected) + menu_entry_frame_execute(frame->selected, ev->xkey.state); + } + } } return ret; @@ -2013,7 +2052,7 @@ static gboolean event_handle_user_input(ObClient *client, XEvent *e) static void focus_delay_dest(gpointer data) { - g_free(data); + g_slice_free(ObFocusDelayData, data); } static gboolean focus_delay_cmp(gconstpointer d1, gconstpointer d2) @@ -2075,7 +2114,7 @@ static void event_ignore_enter_range(gulong start, gulong end) g_assert(start != 0); g_assert(end != 0); - r = g_new(ObSerialRange, 1); + r = g_slice_new(ObSerialRange); r->start = start; r->end = end; ignore_serials = g_slist_prepend(ignore_serials, r); @@ -2110,7 +2149,7 @@ static gboolean is_enter_focus_event_ignored(gulong serial) if ((glong)(serial - r->end) > 0) { /* past the end */ ignore_serials = g_slist_delete_link(ignore_serials, it); - g_free(r); + g_slice_free(ObSerialRange, r); } else if ((glong)(serial - r->start) >= 0) return TRUE;