Пример #1
0
void actions_client_move(ObActionsData *data, gboolean start)
{
    static gulong ignore_start = 0;
    if (start)
        ignore_start = event_start_ignore_all_enters();
    else if (config_focus_follow &&
             data->context != OB_FRAME_CONTEXT_CLIENT)
    {
        if (data->uact == OB_USER_ACTION_MOUSE_PRESS) {
            struct _ObClient *c;
			syslog(LOG_INFO,"client move");
            /* usually this is sorta redundant, but with a press action
               that moves windows our from under the cursor, the enter
               event will come as a GrabNotify which is ignored, so this
               makes a fake enter event

               don't do this if there is a grab on the pointer.  enter events
               are ignored during a grab, so don't force fake ones when they
               should be ignored
            */
            if ((c = client_under_pointer()) && c != data->client &&
                !grab_on_pointer())
            {
                ob_debug_type(OB_DEBUG_FOCUS,
                              "Generating fake enter because we did a "
                              "mouse-event action");
                event_enter_client(c);
            }
        }
        else if (!data->button && !config_focus_under_mouse)
            event_end_ignore_all_enters(ignore_start);
    }
}
Пример #2
0
void menu_show(gchar *name, gint x, gint y, gboolean mouse, ObClient *client)
{
    ObMenu *self;
    ObMenuFrame *frame;

    if (!(self = menu_from_name(name)) ||
        grab_on_keyboard() || grab_on_pointer()) return;

    /* if the requested menu is already the top visible menu, then don't
       bother */
    if (menu_frame_visible) {
        frame = menu_frame_visible->data;
        if (frame->menu == self)
            return;
    }

    menu_frame_hide_all();

    /* clear the pipe menus when showing a new menu */
    menu_clear_pipe_caches();

    frame = menu_frame_new(self, 0, client);
    if (!menu_frame_show_topmenu(frame, x, y, mouse))
        menu_frame_free(frame);
    else {
        if (!mouse) {
            /* select the first entry if it's not a submenu and we opened
             * the menu with the keyboard, and skip all headers */
            GList *it = frame->entries;
            while (it) {
                ObMenuEntryFrame *e = it->data;
                if (e->entry->type == OB_MENU_ENTRY_TYPE_NORMAL) {
                    menu_frame_select(frame, e, FALSE);
                    break;
                } else if (e->entry->type == OB_MENU_ENTRY_TYPE_SEPARATOR)
                    it = g_list_next(it);
                else
                    break;
            }
        }

        /* reset the hide timer */
        if (!mouse)
            menu_can_hide = TRUE;
        else {
            menu_can_hide = FALSE;
            obt_main_loop_timeout_add(ob_main_loop,
                                      config_menu_hide_delay * 1000,
                                      menu_hide_delay_func,
                                      NULL, g_direct_equal, NULL);
        }
    }
}
Пример #3
0
void mouse_event(ObClient *client, XEvent *e)
{
    static Time ltime;
    static guint button = 0, state = 0, lbutton = 0;
    static Window lwindow = None;
    static gint px, py, pwx = -1, pwy = -1;

    ObFrameContext context;
    gboolean click = FALSE;
    gboolean dclick = FALSE;

    switch (e->type) {
    case ButtonPress:
        context = frame_context(client, e->xbutton.window,
                                e->xbutton.x, e->xbutton.y);
        context = mouse_button_frame_context(context, e->xbutton.button,
                                             e->xbutton.state);

        px = e->xbutton.x_root;
        py = e->xbutton.y_root;
        if (!button) pwx = e->xbutton.x;
        if (!button) pwy = e->xbutton.y;
        button = e->xbutton.button;
        state = e->xbutton.state;

        /* if the binding was in a client context, then we need to call
           XAllowEvents with ReplayPointer at some point, to send the event
           through to the client.  when this happens though depends.  if
           windows are going to be moved on screen, then the click will end
           up going somewhere wrong, set that we need it, and if nothing
           else causes the replay pointer to be run, then we will do it
           after all the actions are finished.

           (We do it after all the actions because FocusIn interrupts
           dragging for kdesktop, so if we send the button event now, and
           then they get a focus event after, it breaks.  Instead, wait to send
           the button press until after the actions when possible.)
        */
        if (CLIENT_CONTEXT(context, client))
            replay_pointer_needed = TRUE;

        fire_binding(OB_MOUSE_ACTION_PRESS, context,
                     client, e->xbutton.state,
                     e->xbutton.button,
                     e->xbutton.x_root, e->xbutton.y_root);

        /* if the bindings grab the pointer, there won't be a ButtonRelease
           event for us */
        if (grab_on_pointer())
            button = 0;

        /* replay the pointer event if it hasn't been replayed yet (i.e. no
           windows were moved) */
        mouse_replay_pointer();

        /* in the client context, we won't get a button release because of the
           way it is grabbed, so just fake one */
        if (!CLIENT_CONTEXT(context, client))
            break;

    case ButtonRelease:
        /* use where the press occured in the window */
        context = frame_context(client, e->xbutton.window, pwx, pwy);
        context = mouse_button_frame_context(context, e->xbutton.button,
                                             e->xbutton.state);

        if (e->xbutton.button == button)
            pwx = pwy = -1;

        if (e->xbutton.button == button) {
            /* clicks are only valid if its released over the window */
            gint junk1, junk2;
            Window wjunk;
            guint ujunk, b, w, h;
            /* this can cause errors to occur when the window closes */
            xerror_set_ignore(TRUE);
            junk1 = XGetGeometry(ob_display, e->xbutton.window,
                                 &wjunk, &junk1, &junk2, &w, &h, &b, &ujunk);
            xerror_set_ignore(FALSE);
            if (junk1) {
                if (e->xbutton.x >= (signed)-b &&
                    e->xbutton.y >= (signed)-b &&
                    e->xbutton.x < (signed)(w+b) &&
                    e->xbutton.y < (signed)(h+b)) {
                    click = TRUE;
                    /* double clicks happen if there were 2 in a row! */
                    if (lbutton == button &&
                        lwindow == e->xbutton.window &&
                        e->xbutton.time - config_mouse_dclicktime <=
                        ltime) {
                        dclick = TRUE;
                        lbutton = 0;
                    } else {
                        lbutton = button;
                        lwindow = e->xbutton.window;
                    }
                } else {
                    lbutton = 0;
                    lwindow = None;
                }
            }

            button = 0;
            state = 0;
            ltime = e->xbutton.time;
        }
        fire_binding(OB_MOUSE_ACTION_RELEASE, context,
                     client, e->xbutton.state,
                     e->xbutton.button,
                     e->xbutton.x_root,
                     e->xbutton.y_root);
        if (click)
            fire_binding(OB_MOUSE_ACTION_CLICK, context,
                         client, e->xbutton.state,
                         e->xbutton.button,
                         e->xbutton.x_root,
                         e->xbutton.y_root);
        if (dclick)
            fire_binding(OB_MOUSE_ACTION_DOUBLE_CLICK, context,
                         client, e->xbutton.state,
                         e->xbutton.button,
                         e->xbutton.x_root,
                         e->xbutton.y_root);
        break;

    case MotionNotify:
        if (button) {
            context = frame_context(client, e->xmotion.window, pwx, pwy);
            context = mouse_button_frame_context(context, button, state);

            if (ABS(e->xmotion.x_root - px) >= config_mouse_threshold ||
                ABS(e->xmotion.y_root - py) >= config_mouse_threshold) {

                /* You can't drag on buttons */
                if (context == OB_FRAME_CONTEXT_MAXIMIZE ||
                    context == OB_FRAME_CONTEXT_ALLDESKTOPS ||
                    context == OB_FRAME_CONTEXT_SHADE ||
                    context == OB_FRAME_CONTEXT_ICONIFY ||
                    context == OB_FRAME_CONTEXT_ICON ||
                    context == OB_FRAME_CONTEXT_CLOSE)
                    break;

                fire_binding(OB_MOUSE_ACTION_MOTION, context,
                             client, state, button, px, py);
                button = 0;
                state = 0;
            }
        }
        break;

    default:
        g_assert_not_reached();
    }
}