Skip to content
Snippets Groups Projects
events.c 41.7 KiB
Newer Older
            if(c->startup_id)
            {
                free(c->startup_id);
                c->startup_id = NULL;
            }
Olivier Fourdan's avatar
Olivier Fourdan committed
            getWindowStartupId(dpy, c->window, &c->startup_id);
Olivier Fourdan's avatar
Olivier Fourdan committed
    }
    else
    {
        if(ev->atom == win_workspace_count)
        {
            DBG("root has received a win_workspace_count notify\n");
            getGnomeHint(dpy, root, win_workspace_count, &dummy);
            workspaceSetCount(dummy);
        }
        else if(ev->atom == gnome_panel_desktop_area)
        {
            DBG("root has received a gnome_panel_desktop_area notify\n");
            getGnomeDesktopMargins(dpy, screen, gnome_margins);
            workspaceUpdateArea(margins, gnome_margins);
static inline void handleClientMessage(XClientMessageEvent * ev)
Olivier Fourdan's avatar
Olivier Fourdan committed
{
    Client *c;

    DBG("entering handleClientMessage\n");

    c = clientGetFromWindow(ev->window, WINDOW);
    if(c)
    {
        if((ev->message_type == wm_change_state) && (ev->format == 32) && (ev->data.l[0] == IconicState))
            DBG("client \"%s\" (0x%lx) has received a wm_change_state event\n", c->name, c->window);
            if(CLIENT_CAN_HIDE_WINDOW(c))
Olivier Fourdan's avatar
Olivier Fourdan committed
        else if((ev->message_type == win_state) && (ev->format == 32) && (ev->data.l[0] & WIN_STATE_SHADED))
            DBG("client \"%s\" (0x%lx) has received a win_state/shaded event\n", c->name, c->window);
            if(ev->data.l[1] == WIN_STATE_SHADED)
            {
                clientShade(c);
                clientUnshade(c);
Olivier Fourdan's avatar
Olivier Fourdan committed
            clientToggleShaded(c);
        }
        else if((ev->message_type == win_state) && (ev->format == 32) && (ev->data.l[0] & WIN_STATE_STICKY))
Olivier Fourdan's avatar
Olivier Fourdan committed
        {
            DBG("client \"%s\" (0x%lx) has received a win_state/stick event\n", c->name, c->window);
Olivier Fourdan's avatar
Olivier Fourdan committed
            if(CLIENT_FLAG_TEST(c, CLIENT_FLAG_HAS_STICK))
            {
                if(ev->data.l[1] == WIN_STATE_STICKY)
                {
                frameDraw(c, FALSE, FALSE);
Olivier Fourdan's avatar
Olivier Fourdan committed
        }
        else if((ev->message_type == win_layer) && (ev->format == 32))
        {
            DBG("client \"%s\" (0x%lx) has received a win_layer event\n", c->name, c->window);
Olivier Fourdan's avatar
Olivier Fourdan committed
            clientSetLayer(c, ev->data.l[0]);
        }
        else if((ev->message_type == win_workspace) && (ev->format == 32) && !(c->transient_for))
            DBG("client \"%s\" (0x%lx) has received a win_workspace event\n", c->name, c->window);
            clientSetWorkspace(c, ev->data.l[0], TRUE);
        }
        else if((ev->message_type == net_wm_desktop) && (ev->format == 32))
        {
            DBG("client \"%s\" (0x%lx) has received a net_wm_desktop event\n", c->name, c->window);
Olivier Fourdan's avatar
Olivier Fourdan committed
            if((ev->data.l[0] == (int)0xFFFFFFFF) && CLIENT_FLAG_TEST(c, CLIENT_FLAG_HAS_STICK))
Olivier Fourdan's avatar
Olivier Fourdan committed
                clientStick(c, TRUE);
                clientSetWorkspace(c, ev->data.l[0], TRUE);
Olivier Fourdan's avatar
Olivier Fourdan committed
        else if((ev->message_type == net_close_window) && (ev->format == 32))
            DBG("client \"%s\" (0x%lx) has received a net_close_window event\n", c->name, c->window);
Olivier Fourdan's avatar
Olivier Fourdan committed
        else if((ev->message_type == net_wm_state) && (ev->format == 32))
        {
            DBG("client \"%s\" (0x%lx) has received a net_wm_state event\n", c->name, c->window);
Olivier Fourdan's avatar
Olivier Fourdan committed
        else if((ev->message_type == net_wm_moveresize) && (ev->format == 32))
        {
            DBG("client \"%s\" (0x%lx) has received a net_wm_moveresize event\n", c->name, c->window);
Olivier Fourdan's avatar
Olivier Fourdan committed
            g_message(_("%s: Operation not supported (yet)\n"), g_get_prgname());
Olivier Fourdan's avatar
Olivier Fourdan committed
        else if((ev->message_type == net_active_window) && (ev->format == 32))
        {
            DBG("client \"%s\" (0x%lx) has received a net_active_window event\n", c->name, c->window);
            workspaceSwitch(c->win_workspace, NULL);
            clientShow(c, True);
            clientRaise(c);
            clientSetFocus(c, True);
        }
Olivier Fourdan's avatar
Olivier Fourdan committed
    }
    else
    {
        if(((ev->message_type == win_workspace) || (ev->message_type == net_current_desktop)) && (ev->format == 32))
Olivier Fourdan's avatar
Olivier Fourdan committed
            DBG("root has received a win_workspace or a net_current_desktop event\n");
            workspaceSwitch(ev->data.l[0], NULL);
        }
        else if(((ev->message_type == win_workspace_count) || (ev->message_type == net_number_of_desktops)) && (ev->format == 32))
        {
Olivier Fourdan's avatar
Olivier Fourdan committed
            DBG("root has received a win_workspace_count event\n");
            workspaceSetCount(ev->data.l[0]);
            DBG("unidentified client message for window 0x%lx\n", ev->window);
static inline void handleShape(XShapeEvent * ev)
Olivier Fourdan's avatar
Olivier Fourdan committed
{
    Client *c;

    DBG("entering handleShape\n");

    c = clientGetFromWindow(ev->window, WINDOW);
    if(c)
    {
        frameDraw(c, FALSE, TRUE);
static inline void handleColormapNotify(XColormapEvent * ev)
    DBG("entering handleColormapNotify\n");
    c = clientGetFromWindow(ev->window, WINDOW);
    if((c) && (ev->window == c->window) && (ev->new))
Olivier Fourdan's avatar
Olivier Fourdan committed
void handleEvent(XEvent * ev)
{
    DBG("entering handleEvent\n");

Olivier Fourdan's avatar
Olivier Fourdan committed
    switch (ev->type)
    {
    case KeyPress:
        handleKeyPress((XKeyEvent *) ev);
        break;
    case ButtonPress:
        handleButtonPress((XButtonEvent *) ev);
        break;
    case ButtonRelease:
        handleButtonRelease((XButtonEvent *) ev);
        break;
    case DestroyNotify:
        handleDestroyNotify((XDestroyWindowEvent *) ev);
        break;
    case UnmapNotify:
        handleUnmapNotify((XUnmapEvent *) ev);
        break;
    case MapRequest:
        handleMapRequest((XMapRequestEvent *) ev);
        break;
    case ConfigureRequest:
        handleConfigureRequest((XConfigureRequestEvent *) ev);
        break;
    case EnterNotify:
        handleEnterNotify((XCrossingEvent *) ev);
        break;
    case FocusIn:
        handleFocusIn((XFocusChangeEvent *) ev);
        break;
    case FocusOut:
        handleFocusOut((XFocusChangeEvent *) ev);
        break;
    case PropertyNotify:
        handlePropertyNotify((XPropertyEvent *) ev);
        break;
    case ClientMessage:
        handleClientMessage((XClientMessageEvent *) ev);
        break;
    case ColormapNotify:
        handleColormapNotify((XColormapEvent *) ev);
        break;
    default:
        if(shape && (ev->type == shape_event))
        {
            handleShape((XShapeEvent *) ev);
        }
Olivier Fourdan's avatar
Olivier Fourdan committed
    }
Olivier Fourdan's avatar
Olivier Fourdan committed
    {
            reloadSettings(UPDATE_ALL);
Olivier Fourdan's avatar
Olivier Fourdan committed
            reload = False;
Olivier Fourdan's avatar
Olivier Fourdan committed
            gtk_main_quit();
GtkToXEventFilterStatus xfwm4_event_filter(XEvent * xevent, gpointer data)
Olivier Fourdan's avatar
Olivier Fourdan committed
{
    DBG("entering xfwm4_event_filter\n");
    handleEvent(xevent);
    DBG("leaving xfwm4_event_filter\n");
    return XEV_FILTER_STOP;
}

/* GTK stuff (menu, etc...) */

static void menu_callback(Menu * menu, MenuOp op, Window client_xwindow, gpointer menu_data, gpointer item_data)
Olivier Fourdan's avatar
Olivier Fourdan committed
{
Olivier Fourdan's avatar
Olivier Fourdan committed
    Client *c = NULL;
Olivier Fourdan's avatar
Olivier Fourdan committed
    DBG("entering menu_callback\n");
        menu_event_window = None;
    }

Olivier Fourdan's avatar
Olivier Fourdan committed
    {
        c = (Client *) menu_data;
        c = clientGetFromWindow(c->window, WINDOW);
        if(c)
        {
Olivier Fourdan's avatar
Olivier Fourdan committed
            c->button_pressed[MENU_BUTTON] = False;
Olivier Fourdan's avatar
Olivier Fourdan committed
    }
Olivier Fourdan's avatar
Olivier Fourdan committed
    switch (op)
    {
    case MENU_OP_QUIT:
        gtk_main_quit();
        break;
    case MENU_OP_MAXIMIZE:
    case MENU_OP_UNMAXIMIZE:
        if((c) && CLIENT_CAN_MAXIMIZE_WINDOW(c))
        {
            clientToggleMaximized(c, WIN_STATE_MAXIMIZED);
        }
        break;
    case MENU_OP_MINIMIZE:
        if((c) && CLIENT_CAN_HIDE_WINDOW(c))
        {
            clientHide(c, True);
        }
        break;
    case MENU_OP_MINIMIZE_ALL:
        clientHideAll(c);
        break;
    case MENU_OP_UNMINIMIZE:
        if(c)
        {
            clientShow(c, True);
        }
        break;
    case MENU_OP_SHADE:
    case MENU_OP_UNSHADE:
        if(c)
        {
            clientToggleShaded(c);
        }
        break;
    case MENU_OP_STICK:
    case MENU_OP_UNSTICK:
        if(c)
        {
            frameDraw(c, FALSE, FALSE);
            clientToggleSticky(c, TRUE);
        }
        break;
    case MENU_OP_DELETE:
        if(c)
        {
            frameDraw(c, FALSE, FALSE);
            clientClose(c);
        }
        break;
    default:
        if(c)
        {
            frameDraw(c, FALSE, FALSE);
        }
        break;
static gboolean show_popup_cb(GtkWidget * widget, GdkEventButton * ev, gpointer data)
Olivier Fourdan's avatar
Olivier Fourdan committed
{
    Menu *menu;
    MenuOp ops;
    MenuOp insensitive;
    Client *c = NULL;
    gint x = ev->x_root;
    gint y = ev->y_root;

    DBG("entering show_popup_cb\n");

    if(((ev->button == 1) || (ev->button == 3)) && (c = (Client *) data))
    {
        c->button_pressed[MENU_BUTTON] = True;
        frameDraw(c, FALSE, FALSE);
        ops = MENU_OP_DELETE | MENU_OP_MINIMIZE_ALL;
        if(!CLIENT_FLAG_TEST(c, CLIENT_FLAG_HAS_CLOSE))
            insensitive |= MENU_OP_DELETE;
        if(CLIENT_FLAG_TEST(c, CLIENT_FLAG_MAXIMIZED))
            if(!CLIENT_CAN_MAXIMIZE_WINDOW(c))
            if(!CLIENT_CAN_MAXIMIZE_WINDOW(c))
        if(CLIENT_FLAG_TEST(c, CLIENT_FLAG_HIDDEN))
            if(!CLIENT_CAN_HIDE_WINDOW(c))
            if(!CLIENT_CAN_HIDE_WINDOW(c))
        if(CLIENT_FLAG_TEST(c, CLIENT_FLAG_SHADED))
        if(CLIENT_FLAG_TEST(c, CLIENT_FLAG_STICKY))
            if(!CLIENT_FLAG_TEST(c, CLIENT_FLAG_HAS_STICK))
                insensitive |= MENU_OP_UNSTICK;
            if(!CLIENT_FLAG_TEST(c, CLIENT_FLAG_HAS_STICK))
                insensitive |= MENU_OP_STICK;
        }
    }
    else
    {
        return (TRUE);
    }

    if(button_handler_id)
    {
        g_signal_handler_disconnect(GTK_OBJECT(getDefaultGtkWidget()), button_handler_id);
    }
    button_handler_id = g_signal_connect(GTK_OBJECT(getDefaultGtkWidget()), "button_press_event", GTK_SIGNAL_FUNC(show_popup_cb), (gpointer) NULL);

        menu_event_window = None;
    }
    /*
       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.
     */
    menu_event_window = setTmpEventWin(NoEventMask);
    menu = menu_default(ops, insensitive, menu_callback, c);
    if(!menu_popup(menu, x, y, ev->button, ev->time))
        gdk_beep();
        c->button_pressed[MENU_BUTTON] = False;
        frameDraw(c, FALSE, FALSE);
        menu_event_window = None;
static gboolean set_reload(void)
{
    DBG("setting reload flag so all prefs will be reread at next event loop\n");
    reload = True;
    return (TRUE);
}

static gboolean dbl_click_time(void)
{
    GValue tmp_val = { 0, };
    DBG("setting dbl_click_time\n");

    g_value_init(&tmp_val, G_TYPE_INT);
    if(gdk_setting_get("gtk-double-click-time", &tmp_val))
        params.dbl_click_time = abs(g_value_get_int(&tmp_val));
static gboolean client_event_cb(GtkWidget * widget, GdkEventClient * ev)
Olivier Fourdan's avatar
Olivier Fourdan committed
{
    DBG("entering client_event_cb\n");

    if(!atom_rcfiles)
    {
        atom_rcfiles = gdk_atom_intern("_GTK_READ_RCFILES", FALSE);
    }

    if(ev->message_type == atom_rcfiles)
    {
        set_reload();
Olivier Fourdan's avatar
Olivier Fourdan committed
{
    GtkSettings *settings;
    button_handler_id = g_signal_connect(GTK_OBJECT(getDefaultGtkWidget()), "button_press_event", GTK_SIGNAL_FUNC(show_popup_cb), (gpointer) NULL);
    g_signal_connect(GTK_OBJECT(getDefaultGtkWidget()), "client_event", GTK_SIGNAL_FUNC(client_event_cb), (gpointer) NULL);

    settings = gtk_settings_get_default();
        g_signal_connect(settings, "notify::gtk-theme-name", G_CALLBACK(set_reload), NULL);
        g_signal_connect(settings, "notify::gtk-font-name", G_CALLBACK(set_reload), NULL);
        g_signal_connect(settings, "notify::gtk-double-click-time", G_CALLBACK(dbl_click_time), NULL);
Olivier Fourdan's avatar
Olivier Fourdan committed
}