Skip to content
Snippets Groups Projects
events.c 93.4 KiB
Newer Older
            if (ev->data.l[0] == ALL_WORKSPACES)
                if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_HAS_STICK) && !FLAG_TEST (c->flags, CLIENT_FLAG_STICKY))
                    clientStick (c, TRUE);
                    frameQueueDraw (c, FALSE);
            }
            else
            {
                if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_HAS_STICK) && FLAG_TEST (c->flags, CLIENT_FLAG_STICKY))
                    clientUnstick (c, TRUE);
                    frameQueueDraw (c, FALSE);
                }
                if (ev->data.l[0] != (long) c->win_workspace)
Olivier Fourdan's avatar
Olivier Fourdan committed
                    clientSetWorkspace (c, (guint) ev->data.l[0], TRUE);
        else if ((ev->message_type == display_info->atoms[NET_CLOSE_WINDOW]) && (ev->format == 32))
            TRACE ("client \"%s\" (0x%lx) has received a NET_CLOSE_WINDOW event", c->name, c->window);
        else if ((ev->message_type == display_info->atoms[NET_WM_STATE]) && (ev->format == 32))
            TRACE ("client \"%s\" (0x%lx) has received a NET_WM_STATE event", c->name, c->window);
            clientUpdateNetState (c, ev);
        }
        else if ((ev->message_type == display_info->atoms[NET_WM_MOVERESIZE]) && (ev->format == 32))
            TRACE ("client \"%s\" (0x%lx) has received a NET_WM_MOVERESIZE event", c->name, c->window);
            clientNetMoveResize (c, ev);
        else if ((ev->message_type == display_info->atoms[NET_MOVERESIZE_WINDOW]) && (ev->format == 32))
        {
            TRACE ("client \"%s\" (0x%lx) has received a NET_MOVERESIZE_WINDOW event", c->name, c->window);
            clientNetMoveResizeWindow (c, ev);
        }
        else if ((ev->message_type == display_info->atoms[NET_ACTIVE_WINDOW]) && (ev->format == 32))
            TRACE ("client \"%s\" (0x%lx) has received a NET_ACTIVE_WINDOW event", c->name, c->window);
            clientHandleNetActiveWindow (c, (guint32) ev->data.l[1], (gboolean) (ev->data.l[0] == 1));
        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));
        else if (ev->message_type == display_info->atoms[NET_WM_FULLSCREEN_MONITORS])
        {
            TRACE ("client \"%s\" (0x%lx) has received a NET_WM_FULLSCREEN_MONITORS event", c->name, c->window);
            clientSetFullscreenMonitor (c, (gint) ev->data.l[0], (gint) ev->data.l[1],
                                           (gint) ev->data.l[2], (gint) ev->data.l[3]);
        }
        screen_info = myDisplayGetScreenFromWindow (display_info, ev->window);
        if (!screen_info)
        {
        status = EVENT_FILTER_REMOVE;
        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] < (long) screen_info->workspace_count) &&
                (ev->data.l[0] != (long) screen_info->current_ws))
                workspaceSwitch (screen_info, ev->data.l[0], NULL, TRUE,
                                 myDisplayGetTime (display_info, (guint32) ev->data.l[1]));
        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] != (long) 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[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));
        }
        else if ((ev->message_type == display_info->atoms[MANAGER]) && (ev->format == 32))
            TRACE ("window (0x%lx) has received a MANAGER event", ev->window);
            selection = (Atom) ev->data.l[1];
#ifdef ENABLE_KDE_SYSTRAY_PROXY
            if (selection == screen_info->net_system_tray_selection)
            {
                TRACE ("root has received a NET_SYSTEM_TRAY_MANAGER selection event");
                screen_info->systray = getSystrayWindow (display_info, screen_info->net_system_tray_selection);
            }
            else
#endif
            if (myScreenCheckWMAtom (screen_info, selection))
            {
                TRACE ("root has received a WM_Sn selection event");
                display_info->quit = TRUE;
            }
Olivier Fourdan's avatar
Olivier Fourdan committed
        else if (ev->message_type == display_info->atoms[WM_PROTOCOLS])
        {
            if ((Atom) ev->data.l[0] == display_info->atoms[NET_WM_PING])
Olivier Fourdan's avatar
Olivier Fourdan committed
            {
                TRACE ("root has received a NET_WM_PING (pong) event\n");
                clientReceiveNetWMPong (screen_info, (guint32) ev->data.l[1]);
Olivier Fourdan's avatar
Olivier Fourdan committed
            }
        }
            TRACE ("unidentified client message for window 0x%lx", ev->window);
Olivier Fourdan's avatar
Olivier Fourdan committed
    }
static eventFilterStatus
handleSelectionClear (DisplayInfo *display_info, XSelectionClearEvent * ev)
{
    eventFilterStatus status;
    ScreenInfo *screen_info;

    TRACE ("entering handleSelectionClear");

    status = EVENT_FILTER_PASS;
    screen_info = myDisplayGetScreenFromWindow (display_info, ev->window);
    if (screen_info)
    {
        if (myScreenCheckWMAtom (screen_info, ev->selection))
        {
            TRACE ("root has received a WM_Sn selection event");
            display_info->quit = TRUE;
            status = EVENT_FILTER_REMOVE;
        }
    }

    return status;
}

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, SEARCH_WINDOW);
Olivier Fourdan's avatar
Olivier Fourdan committed
    {
        if (ev->kind == ShapeInput)
        {
            frameSetShapeInput (c);
            update = TRUE;
        }
        else if (ev->kind == ShapeBounding)
        {
            if ((ev->shaped) && !FLAG_TEST (c->flags, CLIENT_FLAG_HAS_SHAPE))
            {
                FLAG_SET (c->flags, CLIENT_FLAG_HAS_SHAPE);
                clientGetMWMHints (c, update);
            }
            else if (!(ev->shaped) && FLAG_TEST (c->flags, CLIENT_FLAG_HAS_SHAPE))
            {
                FLAG_UNSET (c->flags, CLIENT_FLAG_HAS_SHAPE);
                clientGetMWMHints (c, update);
            frameQueueDraw (c, FALSE);
Olivier Fourdan's avatar
Olivier Fourdan committed
    }
handleColormapNotify (DisplayInfo *display_info, XColormapEvent * ev)
Olivier Fourdan's avatar
Olivier Fourdan committed
    Client *c;
    TRACE ("entering handleColormapNotify");
    c = myDisplayGetClientFromWindow (display_info, ev->window, SEARCH_WINDOW);
    if ((c) && (ev->window == c->window) && (ev->new))
        if (c == clientGetFocus ())
        {
            clientInstallColormaps (c);
        }
static eventFilterStatus
handleReparentNotify (DisplayInfo *display_info, XReparentEvent * ev)
{
    TRACE ("entering handleReparentNotify, 0x%lx reparented in 0x%lx", ev->window, ev->parent);
    return EVENT_FILTER_PASS;
}

#ifdef HAVE_XSYNC
handleXSyncAlarmNotify (DisplayInfo *display_info, XSyncAlarmNotifyEvent * ev)
{
    Client *c;

    TRACE ("entering handleXSyncAlarmNotify");

    c = myDisplayGetClientFromXSyncAlarm (display_info, ev->alarm);
    if (c)
    {
        c->xsync_waiting = FALSE;
        c->xsync_value = ev->counter_value;
}
#endif /* HAVE_XSYNC */

handleEvent (DisplayInfo *display_info, XEvent * ev)
Olivier Fourdan's avatar
Olivier Fourdan committed
{
    eventFilterStatus status;
    status = EVENT_FILTER_PASS;

    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
    switch (ev->type)
    {
            status = handleMotionNotify (display_info, (XMotionEvent *) ev);
            status = handleKeyPress (display_info, (XKeyEvent *) ev);
            break;
        case KeyRelease:
            status = handleKeyRelease (display_info, (XKeyEvent *) ev);
            status = handleButtonPress (display_info, (XButtonEvent *) ev);
            status = handleButtonRelease (display_info, (XButtonEvent *) ev);
            status = handleDestroyNotify (display_info, (XDestroyWindowEvent *) ev);
            status = handleUnmapNotify (display_info, (XUnmapEvent *) ev);
            status = handleMapRequest (display_info, (XMapRequestEvent *) ev);
Olivier Fourdan's avatar
Olivier Fourdan committed
        case MapNotify:
            status = handleMapNotify (display_info, (XMapEvent *) ev);
Olivier Fourdan's avatar
Olivier Fourdan committed
            break;
Olivier Fourdan's avatar
Olivier Fourdan committed
        case ConfigureNotify:
            status = handleConfigureNotify (display_info, (XConfigureEvent *) ev);
Olivier Fourdan's avatar
Olivier Fourdan committed
            break;
            status = handleConfigureRequest (display_info, (XConfigureRequestEvent *) ev);
            status = handleEnterNotify (display_info, (XCrossingEvent *) ev);
            status = handleLeaveNotify (display_info, (XCrossingEvent *) ev);
            status = handleFocusIn (display_info, (XFocusChangeEvent *) ev);
            status = handleFocusOut (display_info, (XFocusChangeEvent *) ev);
            status = handlePropertyNotify (display_info, (XPropertyEvent *) ev);
            status = handleClientMessage (display_info, (XClientMessageEvent *) ev);
        case SelectionClear:
            status = handleSelectionClear (display_info, (XSelectionClearEvent *) ev);
            break;
            handleColormapNotify (display_info, (XColormapEvent *) ev);
        case ReparentNotify:
            status = handleReparentNotify (display_info, (XReparentEvent *) ev);
            break;
            if ((display_info->have_shape) && (ev->type == display_info->shape_event_base))
                status = handleShape (display_info, (XShapeEvent *) ev);
#ifdef HAVE_XSYNC
            if ((display_info->have_xsync) && (ev->type == (display_info->xsync_event_base + XSyncAlarmNotify)))
            {
                status = handleXSyncAlarmNotify (display_info, (XSyncAlarmNotifyEvent *) ev);
            }
#endif /* HAVE_XSYNC */
Olivier Fourdan's avatar
Olivier Fourdan committed
            break;
    if (!gdk_events_pending () && !XPending (display_info->dpy))
            reloadSettings (display_info, UPDATE_ALL);
            /*
             * Qutting on purpose, update session manager so
             * it does not restart the program immediately
            xfce_sm_client_set_restart_style(display_info->session, XFCE_SM_CLIENT_RESTART_NORMAL);
Olivier Fourdan's avatar
Olivier Fourdan committed
    }
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");
    status = handleEvent (display_info, xevent);
    TRACE ("leaving xfwm4_event_filter");
    return EVENT_FILTER_STOP | status;
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 = myScreenGetClientFromWindow (screen_info, xid, SEARCH_WINDOW);
        c->button_status[MENU_BUTTON] = BUTTON_STATE_NORMAL;
            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))
                {
                    clientWithdraw (c, c->win_workspace, TRUE);
            case MENU_OP_MOVE:
                clientMove (c, NULL);
                break;
            case MENU_OP_RESIZE:
                clientResize (c, CORNER_BOTTOM_RIGHT, NULL);
                break;
                clientWithdrawAll (c, c->win_workspace);
                if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_WAS_SHOWN))
                {
                    clientClearAllShowDesktop (c->screen_info);
                }
                clientShow (c, TRUE);
                break;
            case MENU_OP_SHADE:
            case MENU_OP_UNSHADE:
                clientToggleShaded (c);
                break;
            case MENU_OP_STICK:
            case MENU_OP_UNSTICK:
                clientToggleSticky (c, TRUE);
                frameQueueDraw (c, FALSE);
                break;
            case MENU_OP_WORKSPACES:
                clientSetWorkspace (c, GPOINTER_TO_INT (item_data), TRUE);
                break;
            case MENU_OP_DELETE:
                clientClose (c);
                break;
            case MENU_OP_CONTEXT_HELP:
                clientEnterContextMenuState (c);
                break;
            case MENU_OP_ABOVE:
                clientSetLayerNormal (c);
                break;
            case MENU_OP_BELOW:
                clientToggleLayerBelow (c);
                break;
            case MENU_OP_FULLSCREEN:
            case MENU_OP_UNFULLSCREEN:
                clientToggleFullscreen (c);
                break;
                frameQueueDraw (c, FALSE);
Olivier Fourdan's avatar
Olivier Fourdan committed
    }
Olivier Fourdan's avatar
Olivier Fourdan committed
    {
    xfwmWindowInit (&menu_event_window);
show_window_menu (Client *c, gint px, gint py, guint button, guint32 timestamp)
Olivier Fourdan's avatar
Olivier Fourdan committed
{
Olivier Fourdan's avatar
Olivier Fourdan committed
    ScreenInfo *screen_info;
    DisplayInfo *display_info;
    gboolean is_transient;
    if ((button != Button1) && (button != Button3))
    {
        return;
    }

    if (!c || !FLAG_TEST_ALL (c->xfwm_flags, XFWM_FLAG_HAS_BORDER | XFWM_FLAG_VISIBLE))
    screen_info = c->screen_info;
    display_info = screen_info->display_info;
    is_transient = clientIsValidTransientOrModal (c);
    c->button_status[MENU_BUTTON] = BUTTON_STATE_PRESSED;
    frameQueueDraw (c, FALSE);
    ops = MENU_OP_DELETE | MENU_OP_MINIMIZE_ALL | MENU_OP_WORKSPACES | MENU_OP_MOVE | MENU_OP_RESIZE;
    if (FLAG_TEST (c->flags, CLIENT_FLAG_MAXIMIZED))
    {
        ops |= MENU_OP_UNMAXIMIZE;
    }
    else
    {
        ops |= MENU_OP_MAXIMIZE;
    }
    if (!FLAG_TEST (c->xfwm_flags, XFWM_FLAG_HAS_MOVE))
    {
        insensitive |= MENU_OP_MOVE;
    }

    if (FLAG_TEST (c->flags, CLIENT_FLAG_ICONIFIED))
    {
        ops |= MENU_OP_UNMINIMIZE;
    }
    else
    {
        ops |= 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))
    {
        ops |= MENU_OP_UNSTICK;
    }
    else
    {
        ops |= MENU_OP_STICK;
    }

    if (!FLAG_TEST (c->xfwm_flags, XFWM_FLAG_HAS_CLOSE))
    if (is_transient || !FLAG_TEST(c->xfwm_flags, XFWM_FLAG_HAS_STICK))
    {
        insensitive |= MENU_OP_STICK | MENU_OP_UNSTICK;
    }

    if (!CLIENT_CAN_HIDE_WINDOW (c))
    {
        insensitive |= MENU_OP_MINIMIZE;
    }

    if (!CLIENT_CAN_MAXIMIZE_WINDOW (c))
    {
        insensitive |= MENU_OP_MAXIMIZE;
    }

    if (!FLAG_TEST (c->xfwm_flags, XFWM_FLAG_HAS_MOVE))
    {
        insensitive |= MENU_OP_MOVE;
    }

    if (!FLAG_TEST_ALL (c->xfwm_flags, XFWM_FLAG_HAS_RESIZE | XFWM_FLAG_IS_RESIZABLE) ||
        FLAG_TEST_ALL (c->flags, CLIENT_FLAG_MAXIMIZED))
    {
        insensitive |= MENU_OP_RESIZE;
    }

    if (FLAG_TEST (c->flags, CLIENT_FLAG_FULLSCREEN))
    {
        insensitive |= MENU_OP_SHADE | MENU_OP_MOVE | MENU_OP_RESIZE | MENU_OP_MAXIMIZE | MENU_OP_UNMAXIMIZE;
    }

    if (FLAG_TEST(c->flags, CLIENT_FLAG_FULLSCREEN))
    {
        ops |= MENU_OP_UNFULLSCREEN;
    }
    else
    {
        ops |= MENU_OP_FULLSCREEN;
    }

    if (is_transient || (c->type != WINDOW_NORMAL))
    {
        insensitive |= MENU_OP_FULLSCREEN | MENU_OP_UNFULLSCREEN;
        ops |= MENU_OP_NORMAL | MENU_OP_BELOW;
    }
    else if (FLAG_TEST(c->flags, CLIENT_FLAG_BELOW))
    {
        ops |= MENU_OP_NORMAL | MENU_OP_ABOVE;
    if (is_transient || FLAG_TEST (c->flags, CLIENT_FLAG_FULLSCREEN))
    {
        insensitive |= MENU_OP_NORMAL | MENU_OP_ABOVE | MENU_OP_BELOW;
    }

    /* KDE extension */
    clientGetWMProtocols(c);
    if (FLAG_TEST (c->wm_flags, WM_FLAG_CONTEXT_HELP))
    {
        ops |= MENU_OP_CONTEXT_HELP;
        || !FLAG_TEST (c->xfwm_flags, XFWM_FLAG_HAS_STICK)
        || FLAG_TEST (c->flags, CLIENT_FLAG_STICKY))
    {
        insensitive |= MENU_OP_WORKSPACES;
    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) behavior, 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, button, timestamp))
        TRACE ("Cannot open menu");
        gdk_beep ();
        c->button_status[MENU_BUTTON] = BUTTON_STATE_NORMAL;
        frameQueueDraw (c, FALSE);
        xfwmWindowDelete (&menu_event_window);
}

static gboolean
show_popup_cb (GtkWidget * widget, GdkEventButton * ev, gpointer data)
{
    TRACE ("entering show_popup_cb");

    show_window_menu ((Client *) data, (gint) ev->x_root, (gint) ev->y_root, ev->button, ev->time);

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);
}

double_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->double_click_time = abs (g_value_get_int (&tmp_val));
    }

    return (TRUE);
}

static gboolean
double_click_distance_cb (GObject * obj, GdkEvent * ev, gpointer data)
{
    DisplayInfo *display_info;
    GValue tmp_val = { 0, };

    display_info = (DisplayInfo *) data;
    g_return_val_if_fail (display_info, TRUE);

    g_value_init (&tmp_val, G_TYPE_INT);
    if (gdk_setting_get ("gtk-double-click-distance", &tmp_val))
    {
        display_info->double_click_distance = 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);
refresh_font_cb (GObject * obj, GdkEvent * ev, gpointer data)
{
    ScreenInfo *screen_info;

    screen_info = (ScreenInfo *) data;
    g_return_val_if_fail (screen_info, TRUE);

    myScreenUpdateFontHeight (screen_info);
    clientUpdateAllFrames (screen_info, UPDATE_FRAME);
    return (TRUE);
}

Olivier Fourdan's avatar
Olivier Fourdan committed
/*
 * The size-changed signal is emitted when the pixel width or height
 * of a screen changes.
 */
static void
size_changed_cb(GdkScreen *gscreen, gpointer data)
{
    ScreenInfo *screen_info;
    DisplayInfo *display_info;

    TRACE ("entering size_changed_cb");

    screen_info = (ScreenInfo *) data;
    g_return_if_fail (screen_info);
    display_info = screen_info->display_info;
    if (gdk_screen_get_n_monitors (screen_info->gscr) == 0)
    {
        /*
Olivier Fourdan's avatar
Olivier Fourdan committed
         * Recent Xorg drivers disable the output when the lid
         * is closed, leaving no active monitor, in that case simply
         * ignore the event to avoid messing with windows' positions.
    size_changed = myScreenComputeSize (screen_info);
    if (size_changed)
    {
Olivier Fourdan's avatar
Olivier Fourdan committed
        myScreenInvalidateMonitorCache (screen_info);

        setNetWorkarea (display_info, screen_info->xroot, screen_info->workspace_count,
                        screen_info->width, screen_info->height, screen_info->margins);

        placeSidewalks (screen_info, screen_info->params->wrap_workspaces);

        clientScreenResize (screen_info, FALSE);

Olivier Fourdan's avatar
Olivier Fourdan committed
/*
 * The monitors-changed signal is emitted when the number, size or
 * position of the monitors attached to the screen change.
 */
static void
monitors_changed_cb(GdkScreen *gscreen, gpointer data)
{
Olivier Fourdan's avatar
Olivier Fourdan committed
    DisplayInfo *display_info;
    gint previous_num_monitors;
    gboolean size_changed;
    screen_info = (ScreenInfo *) data;
    g_return_if_fail (screen_info);
Olivier Fourdan's avatar
Olivier Fourdan committed
    display_info = screen_info->display_info;

    if (gdk_screen_get_n_monitors (screen_info->gscr) == 0)
    {
        /*
         * Recent Xorg drivers disable the output when the lid
         * is closed, leaving no active monitor, in that case simply
         * ignore the event to avoid messing with windows' positions.
         */
        return;
    }
Olivier Fourdan's avatar
Olivier Fourdan committed
     * We have added/removed a monitor or even changed the layout,
     * the cache for monitor position we use in our screen structure
     * is not valid anymore and potentially refers to a monitor that
     * was just removed, so invalidate it.
Olivier Fourdan's avatar
Olivier Fourdan committed
    previous_num_monitors = screen_info->num_monitors;
    myScreenInvalidateMonitorCache (screen_info);
    myScreenRebuildMonitorIndex (screen_info);
    size_changed = myScreenComputeSize (screen_info);

    if (size_changed || (screen_info->num_monitors != previous_num_monitors))
    {

        setNetWorkarea (display_info, screen_info->xroot, screen_info->workspace_count,
                        screen_info->width, screen_info->height, screen_info->margins);

        placeSidewalks (screen_info, screen_info->params->wrap_workspaces);

        clientScreenResize (screen_info, (screen_info->num_monitors < previous_num_monitors));
    }

    if (size_changed)
    {
        compositorUpdateScreenSize (screen_info);
    }
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));
    g_signal_connect (G_OBJECT(screen_info->gscr), "size-changed",
                      G_CALLBACK(size_changed_cb),
                      (gpointer) (screen_info));
    if (gtk_major_version > 2 || (gtk_major_version == 2 && gtk_minor_version >= 13))
        g_signal_connect (G_OBJECT(screen_info->gscr), "monitors-changed",
                          G_CALLBACK(monitors_changed_cb),
                          (gpointer) (screen_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 (double_click_time_cb), (gpointer) (screen_info->display_info));
        g_signal_connect (settings, "notify::gtk-double-click-distance",
            G_CALLBACK (double_click_distance_cb), (gpointer) (screen_info->display_info));
        g_signal_connect_after (settings, "notify::gtk-xft-antialias",
            G_CALLBACK (refresh_font_cb), (gpointer) (screen_info));
        g_signal_connect_after (settings, "notify::gtk-xft-dpi",
            G_CALLBACK (refresh_font_cb), (gpointer) (screen_info));
        g_signal_connect_after (settings, "notify::gtk-xft-hinting",
            G_CALLBACK (refresh_font_cb), (gpointer) (screen_info));
        g_signal_connect_after (settings, "notify::gtk-xft-hintstyle",
            G_CALLBACK (refresh_font_cb), (gpointer) (screen_info));
        g_signal_connect_after (settings, "notify::gtk-xft-rgba",
            G_CALLBACK (refresh_font_cb), (gpointer) (screen_info));
Olivier Fourdan's avatar
Olivier Fourdan committed
}