Skip to content
Snippets Groups Projects
events.c 80.2 KiB
Newer Older
                clientSetFocus (screen_info, c, CurrentTime, NO_FOCUS_FLAG);
            }
        else if (ev->message_type == display_info->atoms[NET_REQUEST_FRAME_EXTENTS])
        {
            TRACE ("client \"%s\" (0x%lx) has received a net_request_frame_extents event", c->name, c->window);
            setNetFrameExtents (display_info, c->window, frameTop (c), frameLeft (c),
                                                         frameRight (c), frameBottom (c));
        screen_info = myDisplayGetScreenFromWindow (display_info, ev->window);
        if (!screen_info)
        {
            return;
        }

        if (((ev->message_type == display_info->atoms[WIN_WORKSPACE]) ||
             (ev->message_type == display_info->atoms[NET_CURRENT_DESKTOP])) && (ev->format == 32))
            TRACE ("root has received a win_workspace or a net_current_desktop event %li", ev->data.l[0]);
            if ((ev->data.l[0] >= 0) && (ev->data.l[0] < screen_info->workspace_count) && (ev->data.l[0] != screen_info->current_ws))
                workspaceSwitch (screen_info, ev->data.l[0], NULL, TRUE);
        else if (((ev->message_type == display_info->atoms[WIN_WORKSPACE_COUNT]) ||
                  (ev->message_type == display_info->atoms[NET_NUMBER_OF_DESKTOPS])) && (ev->format == 32))
        {
            TRACE ("root has received a win_workspace_count event");
            if (ev->data.l[0] != screen_info->workspace_count)
                workspaceSetCount (screen_info, ev->data.l[0]);
                getDesktopLayout(display_info, screen_info->xroot, screen_info->workspace_count, &screen_info->desktop_layout);
        else if ((ev->message_type == display_info->atoms[MANAGER]) && (ev->data.l[1] == screen_info->net_system_tray_selection) && (ev->format == 32))
        {
            TRACE ("root has received a net_system_tray_manager event");
            screen_info->systray = getSystrayWindow (display_info, screen_info->net_system_tray_selection);
        else if ((ev->message_type == display_info->atoms[NET_SHOWING_DESKTOP]) && (ev->format == 32))
        {
            TRACE ("root has received a net_showing_desktop event");
            screen_info->show_desktop = (ev->data.l[0] != 0);
            clientToggleShowDesktop (screen_info);
            setHint (display_info, screen_info->xroot, NET_SHOWING_DESKTOP, ev->data.l[0]);
        else if (ev->message_type == display_info->atoms[NET_REQUEST_FRAME_EXTENTS])
            TRACE ("window (0x%lx) has received a net_request_frame_extents event", ev->window);
            /* Size estimate from the decoration extents */
            setNetFrameExtents (display_info, ev->window,
                                frameDecorationTop (screen_info),
                                frameDecorationLeft (screen_info),
                                frameDecorationRight (screen_info),
                                frameDecorationBottom (screen_info));
        }
            TRACE ("unidentified client message for window 0x%lx", ev->window);
static void
handleShape (DisplayInfo *display_info, XShapeEvent * ev)
Olivier Fourdan's avatar
Olivier Fourdan committed
{
Olivier Fourdan's avatar
Olivier Fourdan committed
    Client *c;
Olivier Fourdan's avatar
Olivier Fourdan committed

    TRACE ("entering handleShape");
Olivier Fourdan's avatar
Olivier Fourdan committed

    c = myDisplayGetClientFromWindow (display_info, ev->window, WINDOW);
Olivier Fourdan's avatar
Olivier Fourdan committed
    {
        if (ev->kind == ShapeBounding)
        {
            if ((ev->shaped) && !FLAG_TEST (c->flags, CLIENT_FLAG_HAS_SHAPE))
            {
                FLAG_SET (c->flags, CLIENT_FLAG_HAS_SHAPE);
            }
            else if (!(ev->shaped) && FLAG_TEST (c->flags, CLIENT_FLAG_HAS_SHAPE))
            {
                FLAG_UNSET (c->flags, CLIENT_FLAG_HAS_SHAPE);
static void
handleColormapNotify (DisplayInfo *display_info, XColormapEvent * ev)
Olivier Fourdan's avatar
Olivier Fourdan committed
    Client *c;
    TRACE ("entering handleColormapNotify");
    c = myDisplayGetClientFromWindow (display_info, ev->window, WINDOW);
    if ((c) && (ev->window == c->window) && (ev->new))
        if (c == clientGetFocus ())
        {
            clientInstallColormaps (c);
        }
static void
handleMappingNotify (DisplayInfo *display_info, XMappingEvent * ev)
{
    GSList *screens;

    TRACE ("entering handleMappingNotify");

    /* Refreshes the stored modifier and keymap information */
    XRefreshKeyboardMapping (ev);
    /* Update internal modifiers masks if necessary */
    if (ev->request == MappingModifier)
    {
        TRACE ("handleMappingNotify: modifiers mapping has changed");
        initModifiers (display_info->dpy);
    }

    /* Regrab all keys if the notify is for keyboard (ie not pointer) */
    if (ev->request != MappingPointer)
    {
        TRACE ("handleMappingNotify: Regrab keys");
        for (screens = display_info->screens; screens; screens = g_slist_next (screens))
        {
            ScreenInfo *screen_info = (ScreenInfo *) screens->data;

            /* We need to reload all the settings to recompute the key bindings... */
            loadSettings (screen_info);

            /* ...then update all frames grabs... */
            clientUpdateAllFrames (screen_info, UPDATE_BUTTON_GRABS);
            /* ...and regrab the keys we have on the root win... */
            myScreenGrabKeys (screen_info);
handleEvent (DisplayInfo *display_info, XEvent * ev)
Olivier Fourdan's avatar
Olivier Fourdan committed
{
    TRACE ("entering handleEvent");
Olivier Fourdan's avatar
Olivier Fourdan committed

    /* Update the display time */
    myDisplayUpdateCurrentTime (display_info, ev);
Olivier Fourdan's avatar
Olivier Fourdan committed
    compositorHandleEvent (display_info, ev);
Olivier Fourdan's avatar
Olivier Fourdan committed
    switch (ev->type)
    {
            handleMotionNotify (display_info, (XMotionEvent *) ev);
            handleKeyPress (display_info, (XKeyEvent *) ev);
            handleButtonPress (display_info, (XButtonEvent *) ev);
            handleButtonRelease (display_info, (XButtonEvent *) ev);
            handleDestroyNotify (display_info, (XDestroyWindowEvent *) ev);
            handleUnmapNotify (display_info, (XUnmapEvent *) ev);
            handleMapRequest (display_info, (XMapRequestEvent *) ev);
Olivier Fourdan's avatar
Olivier Fourdan committed
        case MapNotify:
            handleMapNotify (display_info, (XMapEvent *) ev);
Olivier Fourdan's avatar
Olivier Fourdan committed
            break;
Olivier Fourdan's avatar
Olivier Fourdan committed
        case ConfigureNotify:
            handleConfigureNotify (display_info, (XConfigureEvent *) ev);
Olivier Fourdan's avatar
Olivier Fourdan committed
            break;
            handleConfigureRequest (display_info, (XConfigureRequestEvent *) ev);
            handleEnterNotify (display_info, (XCrossingEvent *) ev);
            handleLeaveNotify (display_info, (XCrossingEvent *) ev);
            handleFocusIn (display_info, (XFocusChangeEvent *) ev);
            handleFocusOut (display_info, (XFocusChangeEvent *) ev);
            handlePropertyNotify (display_info, (XPropertyEvent *) ev);
            handleClientMessage (display_info, (XClientMessageEvent *) ev);
            handleColormapNotify (display_info, (XColormapEvent *) ev);
        case MappingNotify:
            handleMappingNotify (display_info, (XMappingEvent *) ev);
            break;
            if ((display_info->have_shape) && (ev->type == display_info->shape_event_base))
                handleShape (display_info, (XShapeEvent *) ev);
    if (!gdk_events_pending () && !XPending (display_info->dpy))
            reloadSettings (display_info, UPDATE_ALL);
eventFilterStatus
xfwm4_event_filter (XEvent * xevent, gpointer data)
Olivier Fourdan's avatar
Olivier Fourdan committed
{
Olivier Fourdan's avatar
Olivier Fourdan committed
    DisplayInfo *display_info;

    display_info = (DisplayInfo *) data;
    TRACE ("entering xfwm4_event_filter");
    handleEvent (display_info, xevent);
    TRACE ("leaving xfwm4_event_filter");
    return EVENT_FILTER_STOP;
Olivier Fourdan's avatar
Olivier Fourdan committed

menu_callback (Menu * menu, MenuOp op, Window xid, gpointer menu_data, gpointer item_data)
Olivier Fourdan's avatar
Olivier Fourdan committed
{
Olivier Fourdan's avatar
Olivier Fourdan committed
    Client *c;
    TRACE ("entering menu_callback");
    if (!xfwmWindowDeleted(&menu_event_window))
        xfwmWindowDelete (&menu_event_window);
Olivier Fourdan's avatar
Olivier Fourdan committed
    c = NULL;
    if ((menu_data != NULL) && (xid != None))
Olivier Fourdan's avatar
Olivier Fourdan committed
    {
        ScreenInfo *screen_info = (ScreenInfo *) menu_data;
        c = clientGetFromWindow (screen_info, xid, WINDOW);
    }

    if (c)
    {
        c->button_pressed[MENU_BUTTON] = FALSE;

        switch (op)
            case MENU_OP_QUIT:
                gtk_main_quit ();
                break;
            case MENU_OP_MAXIMIZE:
            case MENU_OP_UNMAXIMIZE:
                if (CLIENT_CAN_MAXIMIZE_WINDOW (c))
                {
                    clientToggleMaximized (c, WIN_STATE_MAXIMIZED, TRUE);
                }
                break;
            case MENU_OP_MINIMIZE:
                if (CLIENT_CAN_HIDE_WINDOW (c))
                {
                    clientHide (c, c->win_workspace, TRUE);
                }
                break;
            case MENU_OP_MINIMIZE_ALL:
                clientHideAll (c, c->win_workspace);
                break;
            case MENU_OP_UNMINIMIZE:
                clientShow (c, TRUE);
                clientClearAllShowDesktop (c->screen_info);
                break;
            case MENU_OP_SHADE:
            case MENU_OP_UNSHADE:
                clientToggleShaded (c);
                break;
            case MENU_OP_STICK:
            case MENU_OP_UNSTICK:
                clientToggleSticky (c, TRUE);
                break;
            case MENU_OP_WORKSPACES:
                clientSetWorkspace (c, GPOINTER_TO_INT (item_data), TRUE);
                clientClose (c);
                break;
            case MENU_OP_CONTEXT_HELP:
                clientEnterContextMenuState (c);
                break;
            case MENU_OP_ABOVE:
            case MENU_OP_NORMAL:
                clientToggleAbove (c);
                /* Fall thru */
            default:
Olivier Fourdan's avatar
Olivier Fourdan committed
    }
Olivier Fourdan's avatar
Olivier Fourdan committed
    {
    xfwmWindowInit (&menu_event_window);
static gboolean
show_popup_cb (GtkWidget * widget, GdkEventButton * ev, gpointer data)
Olivier Fourdan's avatar
Olivier Fourdan committed
{
Olivier Fourdan's avatar
Olivier Fourdan committed
    ScreenInfo *screen_info;
    DisplayInfo *display_info;
Olivier Fourdan's avatar
Olivier Fourdan committed
    Client *c;
    gint x;
    gint y;
    TRACE ("entering show_popup_cb");

Olivier Fourdan's avatar
Olivier Fourdan committed
    x = ev->x_root;
    y = ev->y_root;
    c = (Client *) data;
    if ((c) && ((ev->button == 1) || (ev->button == 3)))
        c->button_pressed[MENU_BUTTON] = TRUE;
Olivier Fourdan's avatar
Olivier Fourdan committed
        ops = MENU_OP_DELETE | MENU_OP_MINIMIZE_ALL | MENU_OP_WORKSPACES;
Olivier Fourdan's avatar
Olivier Fourdan committed
        if (!FLAG_TEST (c->xfwm_flags, XFWM_FLAG_HAS_CLOSE))
        if (FLAG_TEST (c->flags, CLIENT_FLAG_MAXIMIZED))
        {
            ops |= MENU_OP_UNMAXIMIZE;
            if (!CLIENT_CAN_MAXIMIZE_WINDOW (c))
            {
                insensitive |= MENU_OP_UNMAXIMIZE;
            }
        }
        else
        {
            ops |= MENU_OP_MAXIMIZE;
            if (!CLIENT_CAN_MAXIMIZE_WINDOW (c))
            {
                insensitive |= MENU_OP_MAXIMIZE;
            }
        }

        if (FLAG_TEST (c->flags, CLIENT_FLAG_ICONIFIED))
        {
            ops |= MENU_OP_UNMINIMIZE;
            if (!CLIENT_CAN_HIDE_WINDOW (c))
            {
                insensitive |= MENU_OP_UNMINIMIZE;
            }
        }
        else
        {
            ops |= MENU_OP_MINIMIZE;
            if (!CLIENT_CAN_HIDE_WINDOW (c))
            {
                insensitive |= MENU_OP_MINIMIZE;
            }
        }

        if (FLAG_TEST (c->flags, CLIENT_FLAG_SHADED))
        {
            ops |= MENU_OP_UNSHADE;
        }
        else
        {
            ops |= MENU_OP_SHADE;
        }

        if (FLAG_TEST (c->flags, CLIENT_FLAG_STICKY))
            if (!CLIENT_CAN_STICK_WINDOW(c))
            {
                insensitive |= MENU_OP_UNSTICK;
            }
        }
        else
        {
            ops |= MENU_OP_STICK;
            if (!CLIENT_CAN_STICK_WINDOW(c))
        /* KDE extension */
        clientGetWMProtocols(c);
        if (FLAG_TEST (c->wm_flags, WM_FLAG_CONTEXT_HELP))
        {
            ops |= MENU_OP_CONTEXT_HELP;
        }
        if (FLAG_TEST(c->flags, CLIENT_FLAG_ABOVE))
            if (clientIsValidTransientOrModal (c) ||
                FLAG_TEST (c->flags, CLIENT_FLAG_BELOW | CLIENT_FLAG_FULLSCREEN))
            if (clientIsValidTransientOrModal (c) ||
                FLAG_TEST (c->flags, CLIENT_FLAG_BELOW | CLIENT_FLAG_FULLSCREEN))
Olivier Fourdan's avatar
Olivier Fourdan committed
            || !FLAG_TEST (c->xfwm_flags, XFWM_FLAG_HAS_STICK)
            || FLAG_TEST (c->flags, CLIENT_FLAG_STICKY))
Olivier Fourdan's avatar
Olivier Fourdan committed
        {
            insensitive |= MENU_OP_WORKSPACES;
        }
    /* c is not null here */
    screen_info = c->screen_info;
    display_info = screen_info->display_info;
    if (screen_info->button_handler_id)
        g_signal_handler_disconnect (GTK_OBJECT (myScreenGetGtkWidget (screen_info)), screen_info->button_handler_id);
    screen_info->button_handler_id = g_signal_connect (GTK_OBJECT (myScreenGetGtkWidget (screen_info)),
                                              "button_press_event", GTK_SIGNAL_FUNC (show_popup_cb), (gpointer) NULL);
    if (!xfwmWindowDeleted(&menu_event_window))
        xfwmWindowDelete (&menu_event_window);
    /*
       Since all button press/release events are catched by the windows frames, there is some
Olivier Fourdan's avatar
Olivier Fourdan committed
       side effect with GTK menu. When a menu is opened, any click on the window frame is not
       detected as a click outside the menu, and the menu doesn't close.
       To avoid this (painless but annoying) behaviour, we just setup a no event window that
       "hides" the events to regular windows.
       That might look tricky, but it's very efficient and save plenty of lines of complicated
Olivier Fourdan's avatar
Olivier Fourdan committed
       code.
       Don't forget to delete that window once the menu is closed, though, or we'll get in
Olivier Fourdan's avatar
Olivier Fourdan committed
       trouble.
     */
                    NULL, 0,
                    screen_info->xroot,
    menu = menu_default (screen_info->gscr, c->window, ops, insensitive, menu_callback,
                         c->win_workspace, screen_info->workspace_count,
                         screen_info->workspace_names, screen_info->workspace_names_items,
    if (!menu_popup (menu, x, y, ev->button, ev->time))
    {
        TRACE ("Cannot open menu");
        gdk_beep ();
        c->button_pressed[MENU_BUTTON] = FALSE;
        xfwmWindowDelete (&menu_event_window);
set_reload (GObject * obj, GdkEvent * ev, gpointer data)
    TRACE ("setting reload flag so all prefs will be reread at next event loop");

    display_info = (DisplayInfo *) data;
    display_info->reload = TRUE;
    return (TRUE);
}

dbl_click_time_cb (GObject * obj, GdkEvent * ev, gpointer data)
Olivier Fourdan's avatar
Olivier Fourdan committed
    DisplayInfo *display_info;
    GValue tmp_val = { 0, };
Olivier Fourdan's avatar
Olivier Fourdan committed
    display_info = (DisplayInfo *) data;
    g_return_val_if_fail (display_info, TRUE);
Olivier Fourdan's avatar
Olivier Fourdan committed

    g_value_init (&tmp_val, G_TYPE_INT);
    if (gdk_setting_get ("gtk-double-click-time", &tmp_val))
        display_info->dbl_click_time = abs (g_value_get_int (&tmp_val));
client_event_cb (GtkWidget * widget, GdkEventClient * ev, gpointer data)
Olivier Fourdan's avatar
Olivier Fourdan committed
{
    TRACE ("entering client_event_cb");
        atom_rcfiles = gdk_atom_intern ("_GTK_READ_RCFILES", FALSE);
    if (ev->message_type == atom_rcfiles)
        set_reload (G_OBJECT (widget), (GdkEvent *) ev, data);
initGtkCallbacks (ScreenInfo *screen_info)
Olivier Fourdan's avatar
Olivier Fourdan committed
{
    GtkSettings *settings;
    screen_info->button_handler_id =
        g_signal_connect (GTK_OBJECT (myScreenGetGtkWidget (screen_info)),
                          "button_press_event", GTK_SIGNAL_FUNC (show_popup_cb), (gpointer) NULL);
    g_signal_connect (GTK_OBJECT (myScreenGetGtkWidget (screen_info)), "client_event",
                      GTK_SIGNAL_FUNC (client_event_cb), (gpointer) (screen_info->display_info));
    settings = gtk_settings_get_default ();
    if (settings)
    {
        g_signal_connect (settings, "notify::gtk-theme-name",
            G_CALLBACK (set_reload), (gpointer) (screen_info->display_info));
        g_signal_connect (settings, "notify::gtk-font-name",
            G_CALLBACK (set_reload), (gpointer) (screen_info->display_info));
        g_signal_connect (settings, "notify::gtk-double-click-time",
            G_CALLBACK (dbl_click_time_cb), (gpointer) (screen_info->display_info));
Olivier Fourdan's avatar
Olivier Fourdan committed
}