Index: plugins/windowlist/windowlist.c =================================================================== --- plugins/windowlist/windowlist.c (revision 19959) +++ plugins/windowlist/windowlist.c (working copy) @@ -6,6 +6,7 @@ * Copyright © 2003 Benedikt Meurer * Copyright © 2006 Jani Monoses * Copyright © 2006 Jasper Huijsmans + * Copyright © 2006 Nick Schermer * * 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 @@ -29,48 +30,53 @@ #include #include #include - #include typedef struct { XfcePanelPlugin *plugin; - GtkWidget *windowlist; + GtkWidget *button; GtkWidget *img; NetkScreen *screen; + + gboolean show_all_workspaces; + gboolean show_windowlist_icons; + int screen_callback_id; - gboolean all_workspaces; GtkTooltips *tooltips; } Windowlist; -/* Panel Plugin Interface */ - +/** + * REGISTER PLUGIN + **/ static void windowlist_construct (XfcePanelPlugin * plugin); XFCE_PANEL_PLUGIN_REGISTER_INTERNAL (windowlist_construct); -/* internal functions */ +/** + * MENU FUNCTIONS + **/ static void -action_menu_deactivated (GtkMenu *menu, GtkMenu *parent) +action_menu_deactivated (GtkMenu *menu, + GtkMenu *parent) { gtk_menu_popdown (parent); g_signal_emit_by_name (parent, "deactivate", 0); } static void -popup_action_menu (GtkWidget * widget, gpointer data) +popup_action_menu (GtkWidget * widget, + gpointer data) { NetkWindow *win = data; static GtkWidget *menu = NULL; if (menu) - { - gtk_widget_destroy (menu); - } + gtk_widget_destroy (menu); menu = netk_create_window_action_menu (win); @@ -82,17 +88,20 @@ } static gboolean -menu_item_clicked (GtkWidget * item, GdkEventButton * ev, gpointer data) +menu_item_clicked (GtkWidget *mi, + GdkEventButton * ev, + gpointer data) { - NetkWindow *win = data; + NetkWindow *netk_window = data; if (ev->button == 1) { - netk_window_activate (win); + netk_workspace_activate(netk_window_get_workspace(netk_window)); + netk_window_activate (netk_window); } else if (ev->button == 3) { - popup_action_menu (item, win); + popup_action_menu (mi, netk_window); return TRUE; } @@ -108,266 +117,319 @@ /* the following two functions are based on xfdesktop code */ static GtkWidget * -create_menu_item (NetkWindow * win, Windowlist * wl) +create_menu_item (NetkWindow * window, + Windowlist * wl, + gint icon_width, + gint icon_height) { - const char *wname = NULL; - GtkWidget *item; + const char *window_name = NULL; + GtkWidget *mi; GString *label; - GdkPixbuf *icon, *tmp = NULL; + GdkPixbuf *icon = NULL, *tmp = NULL; + gboolean truncated = FALSE; - if (netk_window_is_skip_pager (win) || netk_window_is_skip_tasklist (win)) + if (netk_window_is_skip_pager (window) || netk_window_is_skip_tasklist (window)) return NULL; - - wname = netk_window_get_name (win); - label = g_string_new (wname); + + window_name = netk_window_get_name (window); + label = g_string_new (window_name); + if (label->len >= 20) { g_string_truncate (label, 20); g_string_append (label, " ..."); + truncated = TRUE; } - if (netk_window_is_minimized (win)) + if (netk_window_is_minimized (window)) { g_string_prepend (label, "["); g_string_append (label, "]"); } + + /* Italic fonts are not completely shown */ + g_string_append (label, " "); + + if (wl->show_windowlist_icons) + icon = netk_window_get_icon (window); - icon = netk_window_get_icon (win); if (icon) { GtkWidget *img; gint w, h; + + w = gdk_pixbuf_get_width (icon); + h = gdk_pixbuf_get_height (icon); - w = gdk_pixbuf_get_width (tmp); - h = gdk_pixbuf_get_height (tmp); - if (w != 24 || h != 24) + if (w != icon_width || h != icon_height) { - tmp = gdk_pixbuf_scale_simple (icon, 24, 24, GDK_INTERP_BILINEAR); + tmp = gdk_pixbuf_scale_simple (icon, icon_width, icon_height, GDK_INTERP_BILINEAR); icon = tmp; } + + mi = gtk_image_menu_item_new_with_label (label->str); - item = gtk_image_menu_item_new_with_label (label->str); - gtk_widget_show (item); - img = gtk_image_new_from_pixbuf (icon); - gtk_widget_show (img); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), img); - - if (tmp) - g_object_unref (tmp); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), img); + + if (tmp) + g_object_unref (tmp); } else { - item = gtk_menu_item_new_with_label (label->str); + mi = gtk_menu_item_new_with_label (label->str); } + + if (truncated) + gtk_tooltips_set_tip (wl->tooltips, mi, window_name, NULL); - gtk_tooltips_set_tip (wl->tooltips, item, wname, NULL); - g_string_free (label, TRUE); - return item; + return mi; } static void -menu_deactivated (GtkWidget *menu, GtkToggleButton *tb) +menu_deactivated (GtkWidget *menu, + GtkToggleButton *tb) { gtk_toggle_button_set_active (tb, FALSE); } static void -position_menu (GtkMenu *menu, int *x, int *y, gboolean *push_in, - Windowlist *wl) +position_menu (GtkMenu *menu, + int *x, + int *y, + gboolean *push_in, + Windowlist *wl) { - XfceScreenPosition pos; GtkRequisition req; + GdkScreen *screen; + GdkRectangle geom; + int num; + + gtk_widget_size_request (GTK_WIDGET (menu), &req); + gdk_window_get_origin (GTK_WIDGET (wl->plugin)->window, x, y); + + switch (xfce_panel_plugin_get_screen_position(wl->plugin)) + { + case XFCE_SCREEN_POSITION_SW_H: + case XFCE_SCREEN_POSITION_S: + case XFCE_SCREEN_POSITION_SE_H: + *y -= req.height; + break; - gtk_widget_size_request(GTK_WIDGET(menu), &req); + case XFCE_SCREEN_POSITION_NW_H: + case XFCE_SCREEN_POSITION_N: + case XFCE_SCREEN_POSITION_NE_H: + *y += wl->button->allocation.height; + break; - gdk_window_get_origin (GTK_WIDGET (wl->plugin)->window, x, y); + case XFCE_SCREEN_POSITION_NW_V: + case XFCE_SCREEN_POSITION_W: + case XFCE_SCREEN_POSITION_SW_V: + *x += wl->button->allocation.width; + *y += wl->button->allocation.height - req.height; + break; - pos = xfce_panel_plugin_get_screen_position(wl->plugin); + case XFCE_SCREEN_POSITION_NE_V: + case XFCE_SCREEN_POSITION_E: + case XFCE_SCREEN_POSITION_SE_V: + *x -= req.width; + *y += wl->button->allocation.height - req.height; + break; - switch(pos) { - case XFCE_SCREEN_POSITION_NW_V: - case XFCE_SCREEN_POSITION_W: - case XFCE_SCREEN_POSITION_SW_V: - *x += wl->windowlist->allocation.width; - *y += wl->windowlist->allocation.height - req.height; - break; - - case XFCE_SCREEN_POSITION_NE_V: - case XFCE_SCREEN_POSITION_E: - case XFCE_SCREEN_POSITION_SE_V: - *x -= req.width; - *y += wl->windowlist->allocation.height - req.height; - break; - - case XFCE_SCREEN_POSITION_NW_H: - case XFCE_SCREEN_POSITION_N: - case XFCE_SCREEN_POSITION_NE_H: - *y += wl->windowlist->allocation.height; - break; - - case XFCE_SCREEN_POSITION_SW_H: - case XFCE_SCREEN_POSITION_S: - case XFCE_SCREEN_POSITION_SE_H: - *y -= req.height; - break; - - default: /* floating */ - gdk_display_get_pointer( - gtk_widget_get_display(GTK_WIDGET(wl->plugin)), - NULL, x, y, NULL); + default: /* Floating */ + gdk_display_get_pointer(gtk_widget_get_display(GTK_WIDGET(wl->plugin)), + NULL, + x, y, + NULL); } - if (*x < 0) - *x = 0; - - if (*y < 0) - *y = 0; + screen = gtk_widget_get_screen (wl->button); + num = gdk_screen_get_monitor_at_window (screen, wl->button->window); + gdk_screen_get_monitor_geometry (screen, num, &geom); + + if (*x > geom.x + geom.width - req.width) + *x = geom.x + geom.width - req.width; + + if (*x < geom.x) + *x = geom.x; + + if (*y > geom.y + geom.height - req.height) + *y = geom.y + geom.height - req.height; + + if (*y < geom.y) + *y = geom.y; } static void -plugin_windowlist_clicked (GtkWidget * w, GdkEventButton *ev, Windowlist * wl) +plugin_button_clicked (GtkWidget * w, + GdkEventButton *ev, + Windowlist * wl) { static GtkWidget *menu = NULL; - GtkWidget *item, *label, *img; - NetkWindow *win; - NetkWorkspace *ws, *aws, *winws; - int wscount, i; + GtkWidget *mi, *img; + NetkWindow *window; + NetkWindowState state; + NetkWorkspace *netk_workspace, *active_workspace, *window_workspace; + gint icon_width, icon_height, wscount, i; + const gchar *ws_name = NULL; + gchar *ws_label, *rm_label; GList *windows, *li; + + PangoFontDescription *italic = pango_font_description_from_string ("italic"); + PangoFontDescription *bold = pango_font_description_from_string ("bold"); + PangoFontDescription *bold_italic = pango_font_description_from_string ("bold italic"); if (menu) - { - gtk_widget_destroy (menu); - } + gtk_widget_destroy (menu); + + gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &icon_width, &icon_height); windows = netk_screen_get_windows_stacked (wl->screen); - aws = netk_screen_get_active_workspace (wl->screen); + active_workspace = netk_screen_get_active_workspace (wl->screen); menu = gtk_menu_new (); - item = gtk_menu_item_new_with_label (_("Window List")); - gtk_widget_set_sensitive (item, FALSE); - gtk_widget_show (item); - gtk_widget_show (item); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); - - item = gtk_separator_menu_item_new (); - gtk_widget_show (item); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); - - if (wl->all_workspaces) - { - wscount = netk_screen_get_workspace_count (wl->screen); - } + if (wl->show_all_workspaces) + wscount = netk_screen_get_workspace_count (wl->screen); else - { - wscount = 1; - } + wscount = 1; for (i = 0; i < wscount; i++) { - char ws_name[32]; - const char *realname; - - if (wl->all_workspaces) - { - ws = netk_screen_get_workspace (wl->screen, i); - } + if (wl->show_all_workspaces) + netk_workspace = netk_screen_get_workspace (wl->screen, i); else - { - ws = netk_screen_get_active_workspace (wl->screen); - } + netk_workspace = netk_screen_get_active_workspace (wl->screen); - realname = netk_workspace_get_name (ws); + ws_name = netk_workspace_get_name (netk_workspace); - if (realname) - { - g_snprintf (ws_name, 32, "%s", realname); - } - else - { - g_snprintf (ws_name, 32, "%d", i + 1); - } + if(!ws_name || atoi(ws_name) == i+1) + ws_label = g_strdup_printf(_("Workspace %d"), i+1); + else + ws_label = g_markup_printf_escaped("%s", ws_name); - item = gtk_menu_item_new_with_label (ws_name); - g_signal_connect_swapped (item, "activate", - G_CALLBACK (netk_workspace_activate), ws); + mi = gtk_menu_item_new_with_label (ws_label); + g_free (ws_label); + g_signal_connect_swapped (mi, "activate", + G_CALLBACK (netk_workspace_activate), netk_workspace); - label = gtk_bin_get_child (GTK_BIN (item)); - gtk_label_set_use_markup (GTK_LABEL (label), TRUE); - gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); + if (netk_workspace == active_workspace) + gtk_widget_modify_font (gtk_bin_get_child (GTK_BIN (mi)), + bold); + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi); - gtk_widget_show (item); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + mi = gtk_separator_menu_item_new (); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi); - if (ws == aws) - { - gtk_widget_set_sensitive (item, FALSE); - } - - item = gtk_separator_menu_item_new (); - gtk_widget_show (item); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); - for (li = windows; li; li = li->next) { - win = li->data; - winws = netk_window_get_workspace (win); - if (ws != winws && !(netk_window_is_sticky (win) && ws == aws)) - { - continue; - } + window = li->data; + window_workspace = netk_window_get_workspace (window); + if (netk_workspace != window_workspace && !(netk_window_is_sticky (window) && netk_workspace == active_workspace)) + continue; + + state = netk_window_get_state (window); - item = create_menu_item (win, wl); + mi = create_menu_item (window, + wl, + icon_width, + icon_height); - if (!item) + if (!mi) continue; - - if (ws != aws) + + if(state & NETK_WINDOW_STATE_URGENT && netk_workspace == active_workspace) + { + gtk_widget_modify_font (gtk_bin_get_child (GTK_BIN (mi)), + bold); + } + else if (state & NETK_WINDOW_STATE_URGENT) + { + gtk_widget_modify_fg (gtk_bin_get_child (GTK_BIN (mi)), + GTK_STATE_NORMAL, + &(menu->style->fg[GTK_STATE_INSENSITIVE])); + gtk_widget_modify_font (gtk_bin_get_child (GTK_BIN (mi)), + bold_italic); + } + else if (netk_workspace != active_workspace) { - gtk_widget_modify_fg (gtk_bin_get_child (GTK_BIN (item)), + gtk_widget_modify_fg (gtk_bin_get_child (GTK_BIN (mi)), GTK_STATE_NORMAL, &(menu->style->fg[GTK_STATE_INSENSITIVE])); + gtk_widget_modify_font (gtk_bin_get_child (GTK_BIN (mi)), + italic); } - g_signal_connect (item, "button-release-event", - G_CALLBACK (menu_item_clicked), win); + g_signal_connect (mi, "button-release-event", + G_CALLBACK (menu_item_clicked), window); - gtk_widget_show (item); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi); } - item = gtk_separator_menu_item_new (); - gtk_widget_show (item); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + mi = gtk_separator_menu_item_new (); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi); } + + pango_font_description_free(italic); + pango_font_description_free(bold); + pango_font_description_free(bold_italic); + /* Count workspace number */ wscount = netk_screen_get_workspace_count (wl->screen); - item = gtk_image_menu_item_new_with_label (_("Add workspace")); - gtk_widget_show (item); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); - g_signal_connect_swapped (item, "activate", G_CALLBACK (set_num_screens), - GINT_TO_POINTER (wscount + 1)); + /* Add workspace */ + if (wl->show_windowlist_icons) + { + mi = gtk_image_menu_item_new_with_label (_("Add workspace")); + img = gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_MENU); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), img); + } + else + { + mi = gtk_menu_item_new_with_label (_("Add workspace")); + } + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi); + g_signal_connect_swapped (mi, "activate", G_CALLBACK (set_num_screens), + GINT_TO_POINTER (wscount + 1)); - img = gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_MENU); - gtk_widget_show (img); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), img); + /* Remove workspace */ + if (!wl->show_all_workspaces) + { + netk_workspace = netk_screen_get_workspace (wl->screen, wscount-1); + ws_name = netk_workspace_get_name (netk_workspace); + } - item = gtk_image_menu_item_new_with_label (_("Delete workspace")); - gtk_widget_show (item); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); - g_signal_connect_swapped (item, "activate", G_CALLBACK (set_num_screens), + if(!ws_name || atoi(ws_name) == wscount) + rm_label = g_strdup_printf(_("Remove Workspace %d"), wscount); + else + rm_label = g_markup_printf_escaped(_("Remove Workspace '%s'"), ws_name); + + if (wl->show_windowlist_icons) + { + mi = gtk_image_menu_item_new_with_label (rm_label); + img = gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), img); + } + else + { + mi = gtk_menu_item_new_with_label (rm_label); + } + + g_free (rm_label); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi); + g_signal_connect_swapped (mi, "activate", G_CALLBACK (set_num_screens), GINT_TO_POINTER (wscount - 1)); - - img = gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU); - gtk_widget_show (img); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), img); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (wl->windowlist), TRUE); + /* Activate toggle button */ + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (wl->button), TRUE); + g_signal_connect (menu, "deactivate", G_CALLBACK (menu_deactivated), - wl->windowlist); + wl->button); + + gtk_widget_show_all (menu); gtk_menu_popup (GTK_MENU (menu), NULL, NULL, (GtkMenuPositionFunc)position_menu, wl, @@ -379,29 +441,31 @@ { NetkWindow *win; GdkPixbuf *pb; - + if ((win = netk_screen_get_active_window (wl->screen)) != NULL) { pb = netk_window_get_icon (win); if (pb) { xfce_scaled_image_set_from_pixbuf (XFCE_SCALED_IMAGE (wl->img), pb); - gtk_tooltips_set_tip (wl->tooltips, wl->windowlist, + gtk_tooltips_set_tip (wl->tooltips, wl->button, netk_window_get_name (win), NULL); } } } -/* Configuration */ - +/** + * CONFIGURATION + **/ static void windowlist_read_rc_file (XfcePanelPlugin * plugin, Windowlist * wl) { char *file; XfceRc *rc; - int all_workspaces; + gboolean show_all_workspaces, show_windowlist_icons; - all_workspaces = 0; + show_all_workspaces = FALSE; + show_windowlist_icons = TRUE; if ((file = xfce_panel_plugin_lookup_rc_file (plugin)) != NULL) { @@ -410,13 +474,16 @@ if (rc != NULL) { - all_workspaces = xfce_rc_read_int_entry (rc, "all_workspaces", - all_workspaces); + show_all_workspaces = xfce_rc_read_bool_entry (rc, "show_all_workspaces", + show_all_workspaces); + show_windowlist_icons = xfce_rc_read_bool_entry (rc, "show_windowlist_icons", + show_windowlist_icons); xfce_rc_close (rc); } } - wl->all_workspaces = (all_workspaces == 1); + wl->show_all_workspaces = show_all_workspaces; + wl->show_windowlist_icons = show_windowlist_icons; } static void @@ -434,16 +501,22 @@ if (!rc) return; - xfce_rc_write_int_entry (rc, "all_workspaces", wl->all_workspaces); + xfce_rc_write_bool_entry (rc, "show_all_workspaces", wl->show_all_workspaces); + xfce_rc_write_bool_entry (rc, "show_windowlist_icons", wl->show_windowlist_icons); xfce_rc_close (rc); +} +static void +plugin_show_all_changed (GtkToggleButton * cb, Windowlist * wl) +{ + wl->show_all_workspaces = gtk_toggle_button_get_active (cb); } static void -plugin_cb_changed (GtkToggleButton * cb, Windowlist * wl) +plugin_show_windowlist_icons_changed (GtkToggleButton * cb, Windowlist * wl) { - wl->all_workspaces = gtk_toggle_button_get_active (cb); + wl->show_windowlist_icons = gtk_toggle_button_get_active (cb); } static void @@ -480,27 +553,28 @@ header = xfce_create_header (NULL, _("Window List")); gtk_widget_set_size_request (GTK_BIN (header)->child, 200, 32); gtk_container_set_border_width (GTK_CONTAINER (header), 6); - gtk_widget_show (header); gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), header, FALSE, TRUE, 0); mainvbox = gtk_vbox_new (FALSE, 8); gtk_container_set_border_width (GTK_CONTAINER (mainvbox), 5); - gtk_widget_show (mainvbox); gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), mainvbox, TRUE, TRUE, 0); cb = gtk_check_button_new_with_label (_("Include all Workspaces")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cb), wl->all_workspaces); - g_signal_connect (cb, "toggled", G_CALLBACK (plugin_cb_changed), wl); - gtk_widget_show (cb); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cb), wl->show_all_workspaces); + g_signal_connect (cb, "toggled", G_CALLBACK (plugin_show_all_changed), wl); gtk_box_pack_start (GTK_BOX (mainvbox), cb, FALSE, FALSE, 0); + + cb = gtk_check_button_new_with_label (_("Show Window Icons")); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cb), wl->show_windowlist_icons); + g_signal_connect (cb, "toggled", G_CALLBACK (plugin_show_windowlist_icons_changed), wl); + gtk_box_pack_start (GTK_BOX (mainvbox), cb, FALSE, FALSE, 0); - gtk_widget_show (dlg); + gtk_widget_show_all (dlg); } /* Handle free-data signal */ - static void windowlist_free_data (XfcePanelPlugin * plugin, Windowlist * wl) { @@ -519,25 +593,24 @@ wl->tooltips = gtk_tooltips_new (); - wl->all_workspaces = FALSE; wl->screen = netk_screen_get_default (); netk_screen_force_update (wl->screen); - wl->windowlist = gtk_toggle_button_new (); - gtk_button_set_relief (GTK_BUTTON (wl->windowlist), GTK_RELIEF_NONE); - gtk_widget_show (wl->windowlist); + wl->button = gtk_toggle_button_new (); + gtk_button_set_relief (GTK_BUTTON (wl->button), GTK_RELIEF_NONE); + gtk_widget_show (wl->button); pb = gtk_widget_render_icon (GTK_WIDGET (plugin), GTK_STOCK_MISSING_IMAGE, GTK_ICON_SIZE_MENU, NULL); wl->img = xfce_scaled_image_new_from_pixbuf (pb); gtk_widget_show (wl->img); - gtk_container_add (GTK_CONTAINER (wl->windowlist), wl->img); + gtk_container_add (GTK_CONTAINER (wl->button), wl->img); g_object_unref (pb); - xfce_panel_plugin_add_action_widget (plugin, wl->windowlist); - g_signal_connect (wl->windowlist, "button-press-event", - G_CALLBACK (plugin_windowlist_clicked), wl); - + xfce_panel_plugin_add_action_widget (plugin, wl->button); + g_signal_connect (wl->button, "button-press-event", + G_CALLBACK (plugin_button_clicked), wl); + /* set icon */ plugin_active_window_changed (NULL, wl); @@ -545,7 +618,7 @@ g_signal_connect (wl->screen, "active-window-changed", G_CALLBACK (plugin_active_window_changed), wl); - gtk_container_add (GTK_CONTAINER (plugin), wl->windowlist); + gtk_container_add (GTK_CONTAINER (plugin), wl->button); return wl; }