You are not logged in.

#1 2009-08-04 18:45:25

9nqksfhn
Member
Registered: 2009-07-22
Posts: 28

Patch xfwm4.

Hi,

I'm trying to patch xfwm4 (xfce's window manager) to cycle windows differently. With the stock code I hold down Alt and press Tab repeatedly, and it cycles through a list, and when I release Alt and Tab it raises and focuses the window I selected from the list.

xfwm4-window-cycle466.png

The behaviour I want is for it to not display a list at all, and focus the window the moment I press Tab (whilst pressing Alt). So basically I want it to not display a list and to raise + focus the new window instantly as it cycles.

Here is the source code for the window cycling, which I got from here: http://www.p0llux.be/xfce/xfce-4.6.1/sr … .1.tar.bz2 (from src/cycle.c):

/*      $Id: cycle.c 29683 2009-03-25 10:34:05Z olivier $

        This program is free software; you can redistribute it and/or modify
        it under the terms of the GNU General Public License as published by
        the Free Software Foundation; either version 2, or (at your option)
        any later version.

        This program is distributed in the hope that it will be useful,
        but WITHOUT ANY WARRANTY; without even the implied warranty of
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        GNU General Public License for more details.

        You should have received a copy of the GNU General Public License
        along with this program; if not, write to the Free Software
        Foundation, Inc., Inc., 51 Franklin Street, Fifth Floor, Boston,
        MA 02110-1301, USA.


        oroborus - (c) 2001 Ken Lynch
        xfwm4    - (c) 2002-2009 Olivier Fourdan

 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/extensions/shape.h>

#include <glib.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <gtk/gtk.h>
#include <libxfce4util/libxfce4util.h>

#include "client.h"
#include "focus.h"
#include "frame.h"
#include "settings.h"
#include "stacking.h"
#include "tabwin.h"
#include "transients.h"
#include "wireframe.h"
#include "workspaces.h"
#include "event_filter.h"

typedef struct _ClientCycleData ClientCycleData;
struct _ClientCycleData
{
    Client *c;
    Tabwin *tabwin;
    Window wireframe;
    int cycle_range;
};

static eventFilterStatus
clientCycleEventFilter (XEvent * xevent, gpointer data)
{
    ScreenInfo *screen_info;
    DisplayInfo *display_info;
    ClientCycleData *passdata;
    Client *c, *removed;
    eventFilterStatus status;
    KeyCode cancel;
    int key, modifier;
    gboolean key_pressed, cycling, gone;

    TRACE ("entering clientCycleEventFilter");

    passdata = (ClientCycleData *) data;
    if (passdata->c == NULL)
    {
        return EVENT_FILTER_CONTINUE;
    }

    c = passdata->c;
    screen_info = c->screen_info;
    display_info = screen_info->display_info;
    cancel = screen_info->params->keys[KEY_CANCEL].keycode;
    modifier = screen_info->params->keys[KEY_CYCLE_WINDOWS].modifier;
    status = EVENT_FILTER_STOP;
    cycling = TRUE;
    gone = FALSE;

    /* Update the display time */
    myDisplayUpdateCurrentTime (display_info, xevent);

    switch (xevent->type)
    {
        case DestroyNotify:
            removed = myScreenGetClientFromWindow (screen_info, ((XDestroyWindowEvent *) xevent)->window, SEARCH_WINDOW);
            gone |= (c == removed);
            c = tabwinRemoveClient(passdata->tabwin, removed);
            passdata->c = c;
            status = EVENT_FILTER_CONTINUE;
            /* Walk through */
        case UnmapNotify:
            removed = myScreenGetClientFromWindow (screen_info, ((XUnmapEvent *) xevent)->window, SEARCH_WINDOW);
            gone |= (c == removed);
            c = tabwinRemoveClient(passdata->tabwin, removed);
            passdata->c = c;
            status = EVENT_FILTER_CONTINUE;
            /* Walk through */
        case KeyPress:
            key_pressed = (xevent->type == KeyPress);
            if (gone || key_pressed)
            {
                if (key_pressed)
                {
                    Client *c2 = NULL;
                    key = myScreenGetKeyPressed (screen_info, (XKeyEvent *) xevent);
                    /*
                     * We cannot simply check for key == KEY_CANCEL here because of the
                     * mofidier being pressed, so we need to look at the keycode directly.
                     */
                    if (xevent->xkey.keycode == cancel)
                    {
                        c2 = tabwinGetHead (passdata->tabwin);
                        cycling = FALSE;
                    }
                    else if (key == KEY_CYCLE_REVERSE_WINDOWS)
                    {
                        TRACE ("Cycle: previous");
                        c2 = tabwinSelectPrev(passdata->tabwin);
                    }
                    else if (key == KEY_CYCLE_WINDOWS)
                    {
                        TRACE ("Cycle: next");
                        c2 = tabwinSelectNext(passdata->tabwin);
                    }
                    if (c2)
                    {
                        c = c2;
                        passdata->c = c;
                    }

                    /* If last key press event had not our modifier pressed, finish cycling */
                    if (!(xevent->xkey.state & modifier))
                    {
                        cycling = FALSE;
                    }
                }

                if (cycling)
                {
                    if (c)
                    {
                        if (passdata->wireframe)
                        {
                            wireframeUpdate (c, passdata->wireframe);
                        }
                    }
                    else
                    {
                        cycling = FALSE;
                    }
                }
            }
            break;
        case KeyRelease:
            {
                int keysym = XLookupKeysym (&xevent->xkey, 0);

                if (!(xevent->xkey.state & modifier) ||
                    (IsModifierKey(keysym) && (keysym != XK_Shift_L) && (keysym != XK_Shift_R)))
                {
                    cycling = FALSE;
                }
            }
            break;
        case ButtonPress:
        case ButtonRelease:
        case EnterNotify:
        case MotionNotify:
            break;
        default:
            status = EVENT_FILTER_CONTINUE;
            break;
    }

    if (!cycling)
    {
        TRACE ("event loop now finished");
        gtk_main_quit ();
    }

    return status;
}

void
clientCycle (Client * c, XKeyEvent * ev)
{
    ScreenInfo *screen_info;
    DisplayInfo *display_info;
    ClientCycleData passdata;
    gboolean g1, g2;
    int key;

    g_return_if_fail (c != NULL);
    TRACE ("entering clientCycle");

    screen_info = c->screen_info;
    display_info = screen_info->display_info;

    g1 = myScreenGrabKeyboard (screen_info, ev->time);
    g2 = myScreenGrabPointer (screen_info, LeaveWindowMask,  None, ev->time);

    if (!g1 || !g2)
    {
        TRACE ("grab failed in clientCycle");

        gdk_beep ();
        myScreenUngrabKeyboard (screen_info, CurrentTime);
        myScreenUngrabPointer (screen_info, CurrentTime);

        return;
    }

    if (screen_info->params->cycle_hidden)
    {
        passdata.cycle_range = INCLUDE_HIDDEN;
    }
    else
    {
        passdata.cycle_range = 0;
    }
    if (!screen_info->params->cycle_minimum)
    {
        passdata.cycle_range |= INCLUDE_SKIP_TASKBAR | INCLUDE_SKIP_PAGER;
    }
    if (screen_info->params->cycle_workspaces)
    {
        passdata.cycle_range |= INCLUDE_ALL_WORKSPACES;
    }
    key = myScreenGetKeyPressed (screen_info, ev);
    if (key == KEY_CYCLE_REVERSE_WINDOWS)
    {
        passdata.c = clientGetPrevious (c, passdata.cycle_range);
    }
    else
    {
        passdata.c = clientGetNext (c, passdata.cycle_range);
    }
    passdata.wireframe = None;

    /* If there is one single client, and if it's eligible for focus, use it */
    if ((passdata.c == NULL) && (c != clientGetFocus()) &&
        clientSelectMask (c, passdata.cycle_range, WINDOW_REGULAR_FOCUSABLE))
    {
        passdata.c = c;
    }

    if (passdata.c)
    {
        TRACE ("entering cycle loop");
        if (screen_info->params->cycle_draw_frame)
        {
            passdata.wireframe = wireframeCreate (passdata.c);
        }
        passdata.tabwin = tabwinCreate (passdata.c->screen_info->gscr, c,
                                        passdata.c, passdata.cycle_range,
                                        screen_info->params->cycle_workspaces);
        eventFilterPush (display_info->xfilter, clientCycleEventFilter, &passdata);
        gtk_main ();
        eventFilterPop (display_info->xfilter);
        TRACE ("leaving cycle loop");
        tabwinDestroy (passdata.tabwin);
        g_free (passdata.tabwin);
        if (passdata.wireframe)
        {
            wireframeDelete (screen_info, passdata.wireframe);
        }
        updateXserverTime (display_info);
    }

    if (passdata.c)
    {
        Client *focused;
        Client *sibling;
        int workspace;

        c = passdata.c;
        workspace = c->win_workspace;
        focused = clientGetFocus ();

        if (workspace != screen_info->current_ws)
        {
            workspaceSwitch (screen_info, workspace, c, FALSE, myDisplayGetCurrentTime (display_info));
        }

        if ((focused) && (passdata.c != focused))
        {
            clientClearAllShowDesktop (screen_info);
            clientAdjustFullscreenLayer (focused, FALSE);
        }

        sibling = clientGetTransientFor(c);
        clientRaise (sibling, None);
        clientShow (sibling, TRUE);
        clientSetFocus (screen_info, c, myDisplayGetCurrentTime (display_info), NO_FOCUS_FLAG);
        clientSetLastRaise (c);
    }

    /*
     * Use CurrentTime instead of actual last event time to make sure
     * that the grab is released in any case.
     */
    myScreenUngrabKeyboard (screen_info, CurrentTime);
    myScreenUngrabPointer (screen_info, CurrentTime);
}

I don't know any C so I hope someone can help me.

Thanks.

Last edited by 9nqksfhn (2009-08-04 18:47:55)

Offline

#2 2009-08-04 19:12:09

ataraxia
Member
From: Pittsburgh
Registered: 2007-05-06
Posts: 1,553

Re: Patch xfwm4.

This patch might do it. Not tested at all, not even compile tested. I don't use XFCE.

--- cycle.c.orig    2009-08-04 15:04:17.871189695 -0400
+++ cycle.c    2009-08-04 15:07:21.298206230 -0400
@@ -126,11 +126,13 @@
                     {
                         TRACE ("Cycle: previous");
                         c2 = tabwinSelectPrev(passdata->tabwin);
+                        cycling = FALSE;
                     }
                     else if (key == KEY_CYCLE_WINDOWS)
                     {
                         TRACE ("Cycle: next");
                         c2 = tabwinSelectNext(passdata->tabwin);
+                        cycling = FALSE;
                     }
                     if (c2)
                     {

Offline

#3 2009-08-04 19:15:20

9nqksfhn
Member
Registered: 2009-07-22
Posts: 28

Re: Patch xfwm4.

BTW I already get this behaviour by hovering the mouse cursor over the xfce4-panel tasklist plugin and rolling the scroll wheel.

Here is the source code for the xfce4-panel tasklist plugin, which I got from here: http://www.p0llux.be/xfce/xfce-4.6.1/sr … .1.tar.bz2 (from plugins/tasklist/tasklist.c and tasklist-dialogs.c)

/* $Id: tasklist.c 26626 2008-02-18 12:42:14Z nick $
 *
 * Copyright (c) 2005-2007 Jasper Huijsmans <jasper@xfce.org>
 * Copyright (c) 2007      Nick Schermer <nick@xfce.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Library General Public License as published
 * by the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#ifdef HAVE_STRING_H
#include <string.h>
#endif

#include <libwnck/libwnck.h>
#include <libxfce4util/libxfce4util.h>
#include <libxfce4panel/xfce-hvbox.h>

#include "tasklist.h"
#include "tasklist-dialogs.h"

#define TASKLIST_HANDLE_SIZE (8)


/* prototypes */
static gboolean        tasklist_handle_exposed                (GtkWidget          *widget,
                                                               GdkEventExpose     *event,
                                                               TasklistPlugin     *tasklist);
static GdkPixbuf      *tasklist_icon_loader                   (const gchar        *name,
                                                               gint                size,
                                                               guint               flags,
                                                               TasklistPlugin     *tasklist);
static TasklistPlugin *tasklist_plugin_new                    (XfcePanelPlugin    *panel_plugin);
static void            tasklist_plugin_screen_changed         (TasklistPlugin     *tasklist,
                                                               GdkScreen          *previous_screen);
static void            tasklist_plugin_orientation_changed    (TasklistPlugin     *tasklist,
                                                               GtkOrientation      orientation);
static gboolean        tasklist_plugin_size_changed           (TasklistPlugin     *tasklist,
                                                               guint               size);
static void            tasklist_plugin_size_request           (TasklistPlugin     *tasklist,
                                                               GtkRequisition     *requisition);
static void            tasklist_plugin_read                   (TasklistPlugin     *tasklist);
static void            tasklist_plugin_free                   (TasklistPlugin     *tasklist);
static void            tasklist_plugin_construct              (XfcePanelPlugin    *panel_plugin);



/* register with the panel */
XFCE_PANEL_PLUGIN_REGISTER_INTERNAL (tasklist_plugin_construct);



gboolean
tasklist_using_xinerama (XfcePanelPlugin *panel_plugin)
{
    return (gdk_screen_get_n_monitors (gtk_widget_get_screen (GTK_WIDGET (panel_plugin))) > 1);
}



static gboolean
tasklist_handle_exposed (GtkWidget      *widget,
                         GdkEventExpose *event,
                         TasklistPlugin *tasklist)
{
    GtkOrientation orientation;
    gint           x, y, w, h;

    if (GTK_WIDGET_DRAWABLE (widget))
    {
        /* get the panel orientation */
        orientation = xfce_panel_plugin_get_orientation (tasklist->panel_plugin);

        /* set sizes */
        x = widget->allocation.x;
        y = widget->allocation.y;
        w = widget->allocation.width;
        h = widget->allocation.height;

        if (orientation == GTK_ORIENTATION_HORIZONTAL)
        {
            y += widget->style->ythickness;
            h -= 2 * widget->style->ythickness;
        }
        else
        {
            x += widget->style->xthickness;
            w -= 2 * widget->style->xthickness;
        }

        gtk_paint_handle (widget->style, widget->window,
                          GTK_WIDGET_STATE (widget), GTK_SHADOW_NONE,
                          &(event->area), widget, "handlebox",
                          x, y, w, h, orientation);

        return TRUE;
    }

    return FALSE;
}



static GdkPixbuf *
tasklist_icon_loader (const gchar    *name,
                      gint            size,
                      guint           flags,
                      TasklistPlugin *tasklist)
{
    GdkPixbuf   *pixbuf = NULL;
    gchar       *base = NULL;
    const gchar *p;

    /* do nothing on invalid names */
    if (G_UNLIKELY (name == NULL || *name == '\0'))
        return NULL;

    if (g_path_is_absolute (name))
    {
        if (g_file_test (name, G_FILE_TEST_EXISTS))
        {
            /* directly load the file */
            pixbuf = gdk_pixbuf_new_from_file_at_size (name, size, size, NULL);
        }
        else
        {
            /* get the base name */
            base = g_path_get_basename (name);

            /* use this function to try again */
            pixbuf = tasklist_icon_loader (base, size, flags, tasklist);

            /* cleanup */
            g_free (base);
        }
    }
    else
    {
        /* strip prefix */
        p = strrchr (name, '.');
        if (G_UNLIKELY (p))
            base = g_strndup (name, p - name);

        /* load the icon */
        pixbuf = gtk_icon_theme_load_icon (tasklist->icon_theme, base ? base : name, size, 0, NULL);

        /* cleanup */
        g_free (base);
    }

    return pixbuf;
}



static TasklistPlugin *
tasklist_plugin_new (XfcePanelPlugin *panel_plugin)
{
    TasklistPlugin *tasklist;
    GdkScreen      *screen;
    gint            screen_n;

    /* allocate structure */
    tasklist = panel_slice_new0 (TasklistPlugin);

    /* init data */
    tasklist->panel_plugin = panel_plugin;

    /* read settings */
    tasklist_plugin_read (tasklist);

    /* create hvbox */
    tasklist->box = xfce_hvbox_new (xfce_panel_plugin_get_orientation (panel_plugin), FALSE, 0);
    gtk_container_add (GTK_CONTAINER (panel_plugin), tasklist->box);
    gtk_widget_show (tasklist->box);

    /* create handle */
    tasklist->handle = gtk_alignment_new (0.0, 0.0, 0.0, 0.0);
    gtk_widget_set_size_request (tasklist->handle, TASKLIST_HANDLE_SIZE, TASKLIST_HANDLE_SIZE);
    gtk_box_pack_start (GTK_BOX (tasklist->box), tasklist->handle, FALSE, FALSE, 0);
    g_signal_connect (tasklist->handle, "expose-event", G_CALLBACK (tasklist_handle_exposed), tasklist);
    if (tasklist->show_handles)
        gtk_widget_show (tasklist->handle);

    /* get the current screen number */
    screen = gtk_widget_get_screen (GTK_WIDGET (panel_plugin));
    screen_n = gdk_screen_get_number (screen);

    /* set the icon theme */
    tasklist->icon_theme = gtk_icon_theme_get_for_screen (screen);

    /* create tasklist */
    tasklist->list = wnck_tasklist_new (wnck_screen_get (screen_n));
    gtk_box_pack_start (GTK_BOX (tasklist->box), tasklist->list, FALSE, FALSE, 0);
    gtk_widget_show (tasklist->list);

    /* set the tasklist settings */
    wnck_tasklist_set_include_all_workspaces (WNCK_TASKLIST (tasklist->list), tasklist->all_workspaces);
    wnck_tasklist_set_grouping (WNCK_TASKLIST (tasklist->list), tasklist->grouping);
    wnck_tasklist_set_button_relief (WNCK_TASKLIST (tasklist->list), tasklist->flat_buttons ? GTK_RELIEF_NONE : GTK_RELIEF_NORMAL);
    wnck_tasklist_set_icon_loader (WNCK_TASKLIST (tasklist->list), (WnckLoadIconFunction) tasklist_icon_loader, tasklist, NULL);

    return tasklist;
}



static void
tasklist_plugin_screen_changed (TasklistPlugin *tasklist,
                                GdkScreen      *previous_screen)
{
    GdkScreen  *screen;
    WnckScreen *wnck_screen;

    /* get the new screen */
    screen = gtk_widget_get_screen (GTK_WIDGET (tasklist->panel_plugin));
    if (G_UNLIKELY (screen == NULL))
        screen = gdk_screen_get_default ();

    /* get the wnck screen */
    wnck_screen = wnck_screen_get (gdk_screen_get_number (screen));

    /* set the new tasklist screen */
    wnck_tasklist_set_screen (WNCK_TASKLIST (tasklist->list), wnck_screen);

    /* set the icon theme */
    tasklist->icon_theme = gtk_icon_theme_get_for_screen (screen);
}



static void
tasklist_plugin_orientation_changed (TasklistPlugin *tasklist,
                                     GtkOrientation orientation)
{
    /* set the new orientation of the hvbox */
    xfce_hvbox_set_orientation (XFCE_HVBOX (tasklist->box), orientation);

    /* redraw the handle */
    gtk_widget_queue_draw (tasklist->handle);
}



gboolean
tasklist_plugin_size_changed (TasklistPlugin *tasklist,
                              guint           size)
{
    /* size is handled in the size_request function */
    return TRUE;
}



static void
tasklist_plugin_size_request (TasklistPlugin *tasklist,
                              GtkRequisition *requisition)
{
    const gint     *size_hints;
    gint            length;
    gint            size;
    GtkOrientation  orientation;

    /* get the size hints */
    size_hints = wnck_tasklist_get_size_hint_list (WNCK_TASKLIST (tasklist->list), &length);

    /* check for pairs of 2 */
    if (G_LIKELY (length > 0))
    {
        /* get the first size */
        size = size_hints[0];

        /* add the handle size */
        if (tasklist->show_handles)
            size += TASKLIST_HANDLE_SIZE;

        /* use the requested size when it is bigger then the prefered size */
        if (tasklist->width > size)
           size = tasklist->width;

        /* get plugin orientation */
        orientation = xfce_panel_plugin_get_orientation (tasklist->panel_plugin);

        /* set the panel size */
        requisition->width = requisition->height = xfce_panel_plugin_get_size (tasklist->panel_plugin);

        /* set the requested plugin size */
        if (orientation == GTK_ORIENTATION_HORIZONTAL)
            requisition->width = size;
        else
            requisition->height = size;

        /* save the requested size */
        tasklist->req_size = size;
    }
}


static void
tasklist_plugin_size_allocate (TasklistPlugin *tasklist,
                               GtkAllocation  *allocation)
{
  GtkOrientation  orientation;
  gint            a_size, p_size;

  /* get orientation */
  orientation = xfce_panel_plugin_get_orientation (tasklist->panel_plugin);

  /* get plugin size */
  p_size = xfce_panel_plugin_get_size (tasklist->panel_plugin);

  if (orientation == GTK_ORIENTATION_HORIZONTAL)
    a_size = MIN (tasklist->req_size, allocation->width);
  else
    a_size = MIN (tasklist->req_size, allocation->height);

  if (tasklist->show_handles)
    a_size -= TASKLIST_HANDLE_SIZE;

  /* force the size request of the taskbar */
  if (orientation == GTK_ORIENTATION_HORIZONTAL)
    gtk_widget_set_size_request (GTK_WIDGET (tasklist->list), a_size, p_size);
  else
    gtk_widget_set_size_request (GTK_WIDGET (tasklist->list), p_size, a_size);
}


static void
tasklist_plugin_read (TasklistPlugin *tasklist)
{
    gchar  *file;
    XfceRc *rc;

    /* set defaults */
    tasklist->grouping       = WNCK_TASKLIST_AUTO_GROUP;
    tasklist->all_workspaces = FALSE;
    tasklist->expand         = TRUE;
    tasklist->flat_buttons   = TRUE;
    tasklist->show_handles   = TRUE;
    tasklist->width          = 300;

    /* get rc file name */
    file = xfce_panel_plugin_lookup_rc_file (tasklist->panel_plugin);

    if (G_LIKELY (file))
    {
        /* open the file, readonly */
        rc = xfce_rc_simple_open (file, TRUE);

        /* cleanup */
        g_free (file);

        if (G_LIKELY (rc))
        {
            /* read settings */
            tasklist->grouping       = xfce_rc_read_int_entry  (rc, "grouping", tasklist->grouping);
            tasklist->all_workspaces = xfce_rc_read_bool_entry (rc, "all_workspaces", tasklist->all_workspaces);
            tasklist->flat_buttons   = xfce_rc_read_bool_entry (rc, "flat_buttons", tasklist->flat_buttons);
            tasklist->show_handles   = xfce_rc_read_bool_entry (rc, "show_handles", tasklist->show_handles);
            tasklist->width          = xfce_rc_read_int_entry  (rc, "width",tasklist->width);

            /* only set expand flag if xinerama is used */
            if (tasklist_using_xinerama (tasklist->panel_plugin))
                tasklist->expand = xfce_rc_read_bool_entry (rc, "expand", tasklist->expand);

            /* close the rc file */
            xfce_rc_close (rc);
        }
    }
}



void
tasklist_plugin_write (TasklistPlugin *tasklist)
{
    gchar  *file;
    XfceRc *rc;

    /* get rc file name, create it if needed */
    file = xfce_panel_plugin_save_location (tasklist->panel_plugin, TRUE);

    if (G_LIKELY (file))
    {
        /* open the file, writable */
        rc = xfce_rc_simple_open (file, FALSE);

        /* cleanup */
        g_free (file);

        if (G_LIKELY (rc))
        {
            /* write settings */
            xfce_rc_write_int_entry (rc, "grouping", tasklist->grouping);
            xfce_rc_write_int_entry (rc, "width", tasklist->width);
            xfce_rc_write_bool_entry (rc, "all_workspaces", tasklist->all_workspaces);
            xfce_rc_write_bool_entry (rc, "expand", tasklist->expand);
            xfce_rc_write_bool_entry (rc, "flat_buttons", tasklist->flat_buttons);
            xfce_rc_write_bool_entry (rc, "show_handles", tasklist->show_handles);

            /* close the rc file */
            xfce_rc_close (rc);
        }
    }
}



static void
tasklist_plugin_free (TasklistPlugin *tasklist)
{
    GtkWidget *dialog;

    /* destroy the dialog */
    dialog = g_object_get_data (G_OBJECT (tasklist->panel_plugin), I_("dialog"));
    if (dialog)
        gtk_widget_destroy (dialog);

    /* disconnect screen changed signal */
    g_signal_handler_disconnect (G_OBJECT (tasklist->panel_plugin), tasklist->screen_changed_id);

    /* free slice */
    panel_slice_free (TasklistPlugin, tasklist);
}



static void
tasklist_plugin_construct (XfcePanelPlugin *panel_plugin)
{
    TasklistPlugin *tasklist;

    /* create the tray panel plugin */
    tasklist = tasklist_plugin_new (panel_plugin);

    /* set the action widgets and show configure */
    xfce_panel_plugin_add_action_widget (panel_plugin, tasklist->handle);
    xfce_panel_plugin_menu_show_configure (panel_plugin);

    /* whether to expand the plugin */
    xfce_panel_plugin_set_expand (panel_plugin, tasklist->expand);

    /* connect plugin signals */
    g_signal_connect_swapped (G_OBJECT (panel_plugin), "orientation-changed",
                              G_CALLBACK (tasklist_plugin_orientation_changed), tasklist);
    g_signal_connect_swapped (G_OBJECT (panel_plugin), "size-changed",
                              G_CALLBACK (tasklist_plugin_size_changed), tasklist);
    g_signal_connect_swapped (G_OBJECT (panel_plugin), "size-request",
                              G_CALLBACK (tasklist_plugin_size_request), tasklist);
    g_signal_connect_swapped (G_OBJECT (panel_plugin), "size-allocate",
                              G_CALLBACK (tasklist_plugin_size_allocate), tasklist);
    g_signal_connect_swapped (G_OBJECT (panel_plugin), "save",
                              G_CALLBACK (tasklist_plugin_write), tasklist);
    g_signal_connect_swapped (G_OBJECT (panel_plugin), "free-data",
                              G_CALLBACK (tasklist_plugin_free), tasklist);
    g_signal_connect_swapped (G_OBJECT (panel_plugin), "configure-plugin",
                              G_CALLBACK (tasklist_dialogs_configure), tasklist);

    /* screen changed signal */
    tasklist->screen_changed_id =
        g_signal_connect_swapped (G_OBJECT (panel_plugin), "screen-changed",
                                  G_CALLBACK (tasklist_plugin_screen_changed), tasklist);
}
/*  $Id: tasklist-dialogs.c 29188 2009-01-12 17:08:56Z nick $
 *
 *  Copyright (c) 2005-2007 Jasper Huijsmans <jasper@xfce.org>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU Library General Public License as published
 *  by the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "tasklist.h"
#include "tasklist-dialogs.h"



/* prototypes */
static void        tasklist_all_workspaces_toggled     (GtkToggleButton *tb,
                                                        TasklistPlugin  *tasklist);
static void        tasklist_grouping_changed           (GtkComboBox     *cb,
                                                        TasklistPlugin  *tasklist);
static void        tasklist_expand_toggled             (GtkToggleButton *tb,
                                                        TasklistPlugin  *tasklist);
static void        tasklist_flat_buttons_toggled       (GtkToggleButton *tb,
                                                        TasklistPlugin  *tasklist);
static void        tasklist_show_handle_toggled        (GtkToggleButton *tb,
                                                        TasklistPlugin  *tasklist);
static void        tasklist_width_changed              (GtkSpinButton   *sb,
                                                        TasklistPlugin  *tasklist);
static void        tasklist_dialog_response            (GtkWidget       *dlg,
                                                        gint             reponse,
                                                        TasklistPlugin  *tasklist);



static void
tasklist_all_workspaces_toggled (GtkToggleButton *tb,
                                 TasklistPlugin  *tasklist)
{
    tasklist->all_workspaces = gtk_toggle_button_get_active (tb);

    wnck_tasklist_set_include_all_workspaces (WNCK_TASKLIST (tasklist->list),
                                              tasklist->all_workspaces);
}



static void
tasklist_grouping_changed (GtkComboBox    *cb,
                           TasklistPlugin *tasklist)
{
    tasklist->grouping = gtk_combo_box_get_active (cb);

    wnck_tasklist_set_grouping (WNCK_TASKLIST (tasklist->list),
                                tasklist->grouping);
}



static void
tasklist_expand_toggled (GtkToggleButton *tb,
                         TasklistPlugin  *tasklist)
{
    tasklist->expand = gtk_toggle_button_get_active (tb);

    xfce_panel_plugin_set_expand (tasklist->panel_plugin, tasklist->expand);
}



static void
tasklist_flat_buttons_toggled (GtkToggleButton *tb,
                               TasklistPlugin  *tasklist)
{
    tasklist->flat_buttons = gtk_toggle_button_get_active (tb);

    wnck_tasklist_set_button_relief (WNCK_TASKLIST (tasklist->list),
                                     tasklist->flat_buttons ?
                                        GTK_RELIEF_NONE : GTK_RELIEF_NORMAL);
}



static void
tasklist_show_handle_toggled (GtkToggleButton *tb,
                              TasklistPlugin  *tasklist)
{
    tasklist->show_handles = gtk_toggle_button_get_active (tb);

    if (tasklist->show_handles)
        gtk_widget_show (tasklist->handle);
    else
        gtk_widget_hide (tasklist->handle);
}



static void
tasklist_width_changed (GtkSpinButton  *sb,
                        TasklistPlugin *tasklist)
{
    tasklist->width = gtk_spin_button_get_value_as_int (sb);

    gtk_widget_queue_resize (GTK_WIDGET (tasklist->panel_plugin));
}



static void
tasklist_dialog_response (GtkWidget       *dlg,
                          gint             reponse,
                          TasklistPlugin  *tasklist)
{
    g_object_set_data (G_OBJECT (tasklist->panel_plugin), I_("dialog"), NULL);

    gtk_widget_destroy (dlg);
    xfce_panel_plugin_unblock_menu (tasklist->panel_plugin);
    tasklist_plugin_write (tasklist);
}



void
tasklist_dialogs_configure (TasklistPlugin *tasklist)
{
    GtkWidget *dlg, *mainvbox, *vbox, *frame, *cb,
              *hbox, *label, *spin;

    xfce_panel_plugin_block_menu (tasklist->panel_plugin);

    dlg = xfce_titled_dialog_new_with_buttons (_("Task List"), NULL,
                GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
                GTK_STOCK_CLOSE, GTK_RESPONSE_OK,
                NULL);

    gtk_window_set_screen (GTK_WINDOW (dlg), gtk_widget_get_screen (GTK_WIDGET (tasklist->panel_plugin)));

    g_object_set_data (G_OBJECT (tasklist->panel_plugin), I_("dialog"), dlg);

    gtk_window_set_position (GTK_WINDOW (dlg), GTK_WIN_POS_CENTER);
    gtk_window_set_icon_name (GTK_WINDOW (dlg), GTK_STOCK_PROPERTIES);

    g_signal_connect (G_OBJECT (dlg), "response",
                      G_CALLBACK (tasklist_dialog_response), tasklist);

    mainvbox = gtk_vbox_new (FALSE, 6);
    gtk_container_set_border_width (GTK_CONTAINER (mainvbox), 6);
    gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), mainvbox,
                        TRUE, TRUE, 0);

    /* Size */
    vbox = gtk_vbox_new (FALSE, 6);

    frame = xfce_create_framebox_with_content (_("Appearance"), vbox);
    gtk_box_pack_start (GTK_BOX (mainvbox), frame, FALSE, FALSE, 0);

    hbox = gtk_hbox_new (FALSE, 12);
    gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);

    label = gtk_label_new_with_mnemonic (_("_Minimum width:"));
    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
    gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);

    /* an arbitrary max of 4000 should be future proof, right? */
    spin = gtk_spin_button_new_with_range (100, 4000, 10);
    gtk_box_pack_start (GTK_BOX (hbox), spin, FALSE, FALSE, 0);
    gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin), tasklist->width);
    gtk_label_set_mnemonic_widget (GTK_LABEL (label), spin);
    g_signal_connect (G_OBJECT (spin), "value-changed",
                      G_CALLBACK (tasklist_width_changed), tasklist);

    if (tasklist_using_xinerama (tasklist->panel_plugin))
    {
        cb = gtk_check_button_new_with_mnemonic (_("Use all available _space"));
        gtk_box_pack_start (GTK_BOX (vbox), cb, FALSE, FALSE, 0);
        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cb), tasklist->expand);
        g_signal_connect (G_OBJECT (cb), "toggled",
                          G_CALLBACK (tasklist_expand_toggled), tasklist);
    }

    cb = gtk_check_button_new_with_mnemonic (_("Use _flat buttons"));
    gtk_box_pack_start (GTK_BOX (vbox), cb, FALSE, FALSE, 0);
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cb), tasklist->flat_buttons);
    g_signal_connect (G_OBJECT (cb), "toggled",
                      G_CALLBACK (tasklist_flat_buttons_toggled), tasklist);

    cb = gtk_check_button_new_with_mnemonic (_("Show _handle"));
    gtk_box_pack_start (GTK_BOX (vbox), cb, FALSE, FALSE, 0);
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cb), tasklist->show_handles);
    g_signal_connect (G_OBJECT (cb), "toggled",
                      G_CALLBACK (tasklist_show_handle_toggled), tasklist);

    /* Tasks */
    vbox = gtk_vbox_new (FALSE, 6);

    frame = xfce_create_framebox_with_content (_("Task List"), vbox);
    gtk_box_pack_start (GTK_BOX (mainvbox), frame, FALSE, FALSE, 0);

    cb = gtk_check_button_new_with_mnemonic (_("Show tasks from _all workspaces"));
    gtk_box_pack_start (GTK_BOX (vbox), cb, FALSE, FALSE, 0);
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cb), tasklist->all_workspaces);
    g_signal_connect (G_OBJECT (cb), "toggled",
                      G_CALLBACK (tasklist_all_workspaces_toggled), tasklist);

    cb = gtk_combo_box_new_text ();
    gtk_box_pack_start (GTK_BOX (vbox), cb, FALSE, FALSE, 0);

    gtk_combo_box_append_text (GTK_COMBO_BOX (cb), _("Never group tasks"));
    gtk_combo_box_append_text (GTK_COMBO_BOX (cb), _("Automatically group tasks"));
    gtk_combo_box_append_text (GTK_COMBO_BOX (cb), _("Always group tasks"));
    
    /* keep order above in sync with WnckTasklistGroupingType */

    gtk_combo_box_set_active (GTK_COMBO_BOX (cb), tasklist->grouping);

    g_signal_connect (G_OBJECT (cb), "changed",
                      G_CALLBACK (tasklist_grouping_changed), tasklist);

    gtk_widget_show_all (dlg);
}

Offline

#4 2009-08-04 19:16:35

9nqksfhn
Member
Registered: 2009-07-22
Posts: 28

Re: Patch xfwm4.

ataraxia wrote:

This patch might do it. Not tested at all, not even compile tested. I don't use XFCE.

--- cycle.c.orig    2009-08-04 15:04:17.871189695 -0400
+++ cycle.c    2009-08-04 15:07:21.298206230 -0400
@@ -126,11 +126,13 @@
                     {
                         TRACE ("Cycle: previous");
                         c2 = tabwinSelectPrev(passdata->tabwin);
+                        cycling = FALSE;
                     }
                     else if (key == KEY_CYCLE_WINDOWS)
                     {
                         TRACE ("Cycle: next");
                         c2 = tabwinSelectNext(passdata->tabwin);
+                        cycling = FALSE;
                     }
                     if (c2)
                     {

OK, thanks, I will try it smile

Offline

#5 2009-08-04 20:31:32

9nqksfhn
Member
Registered: 2009-07-22
Posts: 28

Re: Patch xfwm4.

When I ran patch it said:

patching file cycle.c
patch unexpectedly ends in middle of line
Hunk #1 succeeded at 126 with fuzz 1.

Is that OK?

Offline

#6 2009-08-04 21:44:34

Heller_Barde
Member
Registered: 2008-04-01
Posts: 245

Re: Patch xfwm4.

check the file it generated, or post the relevant section.

cheers Phil

Offline

#7 2009-08-04 22:45:56

ataraxia
Member
From: Pittsburgh
Registered: 2007-05-06
Posts: 1,553

Re: Patch xfwm4.

9nqksfhn wrote:

When I ran patch it said:

patching file cycle.c
patch unexpectedly ends in middle of line
Hunk #1 succeeded at 126 with fuzz 1.

Is that OK?

That's probably because either you or I didn't paste it with a blank line at the end. Just try it and see.

Offline

#8 2009-08-04 23:08:47

anrxc
Member
From: Croatia
Registered: 2008-03-22
Posts: 834
Website

Re: Patch xfwm4.

9nqksfhn wrote:

I'm trying to patch xfwm4 (xfce's window manager) to cycle windows differently.

Here is the source code for the window cycling, which I got from here: http://www.p0llux.be/xfce/xfce-4.6.1/sr … .1.tar.bz2 (from src/cycle.c)

What will you do when a new XFCE version is released, patch it all over again? When it stops applying you will come here offering prizes again?

I would suggest that you unmap that key binding in XFCE and map it to your own custom program/utility/script which does what you want. You can for example start with using wmctrl.


You need to install an RTFM interface.

Offline

#9 2009-08-05 15:01:05

9nqksfhn
Member
Registered: 2009-07-22
Posts: 28

Re: Patch xfwm4.

ataraxia: Your patch works except the list pops up every other cycle. It's much better than how it was before though, I'm using it at the moment, thanks.

anrxc: That's a good idea, I could write a bash script that uses "wmctrl -l" to get a list of windows and "wmctrl -ai windowcode" to switch the windows, and it lists the windows in the same order each time so I should be able to cycle. But I want a way of telling which window is currently focused so it can cycle in a consistent manner. There seems to be a command "XGetInputFocus" but when I type it it sais "bash: XGetInputFocus: command not found". "man XGetInputFocus" doesn't help.

How can I find out which window is currently focused?

Thanks.

Last edited by 9nqksfhn (2009-08-05 15:02:57)

Offline

Board footer

Powered by FluxBB