From b10257f6b3b9f83470601edbe9eb592abe4949c8 Mon Sep 17 00:00:00 2001 From: Simon Steinbeiss Date: Thu, 5 Feb 2015 22:42:29 +0100 Subject: [PATCH] Add popup when changing workspaces --- src/Makefile.am | 2 + src/events.c | 20 +-- src/workspaces.c | 221 +++++++++++++++++++++++++++++ src/workspaces.h | 3 + src/workspacewin.c | 398 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/workspacewin.h | 76 ++++++++++ 6 files changed, 702 insertions(+), 18 deletions(-) create mode 100644 src/workspacewin.c create mode 100644 src/workspacewin.h diff --git a/src/Makefile.am b/src/Makefile.am index ee2fff6..47d8e0f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -67,6 +67,8 @@ xfwm4_SOURCES = \ wireframe.h \ workspaces.c \ workspaces.h \ + workspacewin.c \ + workspacewin.h \ xsync.c \ xsync.h \ xpm-color-table.h diff --git a/src/events.c b/src/events.c index 719ce41..eaf9b14 100644 --- a/src/events.c +++ b/src/events.c @@ -385,17 +385,10 @@ handleKeyPress (DisplayInfo *display_info, XKeyEvent * ev) workspaceSwitch (screen_info, screen_info->current_ws - 1, c, TRUE, ev->time); break; case KEY_MOVE_UP_WORKSPACE: - workspaceMove (screen_info, -1, 0, c, ev->time); - break; case KEY_MOVE_DOWN_WORKSPACE: - workspaceMove (screen_info, 1, 0, c, ev->time); - break; case KEY_MOVE_LEFT_WORKSPACE: - workspaceMove (screen_info, 0, -1, c, ev->time); - break; case KEY_MOVE_RIGHT_WORKSPACE: - workspaceMove (screen_info, 0, 1, c, ev->time); - break; + workspaceSwitchInteractive (ev_screen_info, c, ev); case KEY_MOVE_WORKSPACE_1: case KEY_MOVE_WORKSPACE_2: case KEY_MOVE_WORKSPACE_3: @@ -513,20 +506,11 @@ handleKeyPress (DisplayInfo *display_info, XKeyEvent * ev) workspaceSwitch (ev_screen_info, ev_screen_info->current_ws - 1, NULL, TRUE, ev->time); break; case KEY_UP_WORKSPACE: - status = EVENT_FILTER_REMOVE; - workspaceMove(ev_screen_info, -1, 0, NULL, ev->time); - break; case KEY_DOWN_WORKSPACE: - status = EVENT_FILTER_REMOVE; - workspaceMove(ev_screen_info, 1, 0, NULL, ev->time); - break; case KEY_LEFT_WORKSPACE: - status = EVENT_FILTER_REMOVE; - workspaceMove(ev_screen_info, 0, -1, NULL, ev->time); - break; case KEY_RIGHT_WORKSPACE: status = EVENT_FILTER_REMOVE; - workspaceMove(ev_screen_info, 0, 1, NULL, ev->time); + workspaceSwitchInteractive (ev_screen_info, NULL, ev); break; case KEY_ADD_WORKSPACE: status = EVENT_FILTER_REMOVE; diff --git a/src/workspaces.c b/src/workspaces.c index 3800429..fc3860c 100644 --- a/src/workspaces.c +++ b/src/workspaces.c @@ -40,12 +40,21 @@ #include "misc.h" #include "transients.h" #include "workspaces.h" +#include "workspacewin.h" #include "settings.h" #include "client.h" #include "focus.h" #include "stacking.h" #include "hints.h" +typedef struct _WorkspaceSwitchData WorkspaceSwitchData; +struct _WorkspaceSwitchData +{ + Wswin *wswin; + ScreenInfo *screen_info; + Client *c; +}; + static void workspaceGetPosition (ScreenInfo *screen_info, int n, int * row, int * col) { @@ -177,6 +186,218 @@ modify_with_wrap (int value, int by, int limit, gboolean wrap) return value; } +static void handle_workspace_event (ScreenInfo * screen_info, Client * c, XKeyEvent * ev) +{ + int key; + + key = myScreenGetKeyPressed (screen_info, ev); + + if(c) + { + switch(key) + { + case KEY_MOVE_UP_WORKSPACE: + workspaceMove (screen_info, -1, 0, c, ev->time); + break; + case KEY_MOVE_DOWN_WORKSPACE: + workspaceMove (screen_info, 1, 0, c, ev->time); + break; + case KEY_MOVE_LEFT_WORKSPACE: + workspaceMove (screen_info, 0, -1, c, ev->time); + break; + case KEY_MOVE_RIGHT_WORKSPACE: + workspaceMove (screen_info, 0, 1, c, ev->time); + break; + } + } + + switch(key) + { + case KEY_UP_WORKSPACE: + workspaceMove (screen_info, -1, 0, NULL, ev->time); + break; + case KEY_DOWN_WORKSPACE: + workspaceMove (screen_info, 1, 0, NULL, ev->time); + break; + case KEY_LEFT_WORKSPACE: + workspaceMove (screen_info, 0, -1, NULL, ev->time); + break; + case KEY_RIGHT_WORKSPACE: + workspaceMove (screen_info, 0, 1, NULL, ev->time); + break; + } +} + +static eventFilterStatus +workspaceSwitchFilter (XEvent * xevent, gpointer data) +{ + ScreenInfo *screen_info; + DisplayInfo *display_info; + WorkspaceSwitchData *passdata; + eventFilterStatus status; + int key, modifiers; + gboolean switching; + Client *c; + + TRACE ("entering workspaceSwitchFilter"); + + passdata = (WorkspaceSwitchData *) data; + + screen_info = passdata->screen_info; + display_info = screen_info->display_info; + modifiers = (screen_info->params->keys[KEY_MOVE_UP_WORKSPACE].modifier || + screen_info->params->keys[KEY_MOVE_DOWN_WORKSPACE].modifier || + screen_info->params->keys[KEY_MOVE_LEFT_WORKSPACE].modifier || + screen_info->params->keys[KEY_MOVE_RIGHT_WORKSPACE].modifier || + screen_info->params->keys[KEY_LEFT_WORKSPACE].modifier || + screen_info->params->keys[KEY_RIGHT_WORKSPACE].modifier || + screen_info->params->keys[KEY_UP_WORKSPACE].modifier || + screen_info->params->keys[KEY_DOWN_WORKSPACE].modifier); + status = EVENT_FILTER_STOP; + + switching = TRUE; + + /* Update the display time */ + myDisplayUpdateCurrentTime (display_info, xevent); + + switch (xevent->type) + { + case KeyPress: + key = myScreenGetKeyPressed (screen_info, (XKeyEvent *) xevent); + c = clientGetFocus (); + if (c) + { + if (key == KEY_MOVE_UP_WORKSPACE || + key == KEY_MOVE_DOWN_WORKSPACE || + key == KEY_MOVE_LEFT_WORKSPACE || + key == KEY_MOVE_RIGHT_WORKSPACE) + { + handle_workspace_event (screen_info, c, (XKeyEvent *) xevent); + wswinSetSelected (passdata->wswin, screen_info->current_ws); + } + } + + if (key == KEY_UP_WORKSPACE || + key == KEY_DOWN_WORKSPACE || + key == KEY_LEFT_WORKSPACE || + key == KEY_RIGHT_WORKSPACE) + { + handle_workspace_event (screen_info, NULL, (XKeyEvent *) xevent); + wswinSetSelected (passdata->wswin, screen_info->current_ws); + } + /* If last key press event didn't have our modifiers pressed, finish workspace switching */ + if (!(xevent->xkey.state & modifiers)) + { + switching = FALSE; + } + break; + case KeyRelease: + { + int keysym = XLookupKeysym (&xevent->xkey, 0); + + if (IsModifierKey(keysym)) + { + if (!(myScreenGetModifierPressed (screen_info) & modifiers)) + { + switching = FALSE; + } + } + } + break; + case ButtonPress: + case ButtonRelease: + case EnterNotify: + case MotionNotify: + break; + default: + status = EVENT_FILTER_CONTINUE; + break; + } + + if (!switching) + { + /* TRACE ("event loop now finished"); */ + gtk_main_quit (); + } + + return status; +} + +void +workspaceSwitchInteractive (ScreenInfo * screen_info, Client * c, XKeyEvent * ev) +{ + /* TODO: add trace statements (to all code) */ + /* TODO: add support for move with current window */ + DisplayInfo *display_info; + gboolean g1, g2; + WorkspaceSwitchData passdata; + int key, modifier; + + display_info = screen_info->display_info; + + modifier = 0; + key = myScreenGetKeyPressed (screen_info, ev); + switch (key) + { + case KEY_MOVE_UP_WORKSPACE: + case KEY_MOVE_DOWN_WORKSPACE: + case KEY_MOVE_LEFT_WORKSPACE: + case KEY_MOVE_RIGHT_WORKSPACE: + case KEY_UP_WORKSPACE: + case KEY_DOWN_WORKSPACE: + case KEY_LEFT_WORKSPACE: + case KEY_RIGHT_WORKSPACE: + modifier = screen_info->params->keys[key].modifier; + } + + if (!modifier) + { + /* + * The shortcut has no modifier so there's no point in entering + * the cycle loop, and we already servied the event above + * that's it... + */ + handle_workspace_event (screen_info, c, ev); + return; + } + + g1 = myScreenGrabKeyboard (screen_info, ev->time); + g2 = myScreenGrabPointer (screen_info, TRUE, LeaveWindowMask, None, ev->time); + + if (!g1 || !g2) + { + TRACE ("grab failed in workspaceSwitchInteractive"); + + gdk_beep (); + myScreenUngrabKeyboard (screen_info, myDisplayGetCurrentTime (display_info)); + myScreenUngrabPointer (screen_info, myDisplayGetCurrentTime (display_info)); + + return; + } + + handle_workspace_event (screen_info, c, ev); + + passdata.c = NULL; + passdata.screen_info = screen_info; + passdata.wswin = wswinCreate(screen_info); + + TRACE ("entering worspace loop"); + + eventFilterPush (display_info->xfilter, workspaceSwitchFilter, &passdata); + gtk_main (); + eventFilterPop (display_info->xfilter); + + TRACE("leaving workspace loop"); + + updateXserverTime (display_info); + + wswinDestroy (passdata.wswin); + g_free (passdata.wswin); + + myScreenUngrabKeyboard (screen_info, myDisplayGetCurrentTime (display_info)); + myScreenUngrabPointer (screen_info, myDisplayGetCurrentTime (display_info)); +} + /* returns TRUE if the workspace was changed, FALSE otherwise */ gboolean workspaceMove (ScreenInfo *screen_info, gint rowmod, gint colmod, Client * c, guint32 timestamp) diff --git a/src/workspaces.h b/src/workspaces.h index 0087743..8861234 100644 --- a/src/workspaces.h +++ b/src/workspaces.h @@ -37,6 +37,9 @@ #include "screen.h" #include "client.h" +void workspaceSwitchInteractive (ScreenInfo *, + Client *, + XKeyEvent *); gboolean workspaceMove (ScreenInfo *, int, int, diff --git a/src/workspacewin.c b/src/workspacewin.c new file mode 100644 index 0000000..8d88f20 --- /dev/null +++ b/src/workspacewin.c @@ -0,0 +1,398 @@ +/* $Id$ + + 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. + + + xfwm4 - (c) 2002-2011 Olivier Fourdan + + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifndef WIN_BORDER_WIDTH +#define WIN_BORDER_WIDTH 1 +#endif + +#ifndef WIN_ALPHA +#define WIN_ALPHA 0.85 +#endif + +#ifndef WIN_BORDER_ALPHA +#define WIN_BORDER_ALPHA 0.5 +#endif + +#ifndef WIN_BORDER_RADIUS +#define WIN_BORDER_RADIUS 10 +#endif + +#include +#include +#include +#include "focus.h" +#include "workspacewin.h" + +static void wswin_widget_class_init (WswinWidgetClass *klass); + +static GType +wswin_widget_get_type (void) +{ + static GType type = G_TYPE_INVALID; + + if (G_UNLIKELY (type == G_TYPE_INVALID)) + { + static const GTypeInfo info = + { + sizeof (WswinWidgetClass), + NULL, + NULL, + (GClassInitFunc) wswin_widget_class_init, + NULL, + NULL, + sizeof (WswinWidget), + 0, + NULL, + NULL, + }; + + type = g_type_register_static (GTK_TYPE_WINDOW, "Xfwm4WswinWidget", &info, 0); + } + + return type; +} + +static gboolean +wswinConfigure (WswinWidget *wsw, GdkEventConfigure *event) +{ + GtkWindow *window; + GdkRectangle monitor; + GdkScreen *screen; + gint x, y; + + g_return_val_if_fail(wsw != NULL, FALSE); + TRACE ("entering wswinConfigure"); + + if ((wsw->width == event->width) && (wsw->height == event->height)) + { + return FALSE; + } + + window = GTK_WINDOW(wsw); + screen = gtk_window_get_screen(window); + gdk_screen_get_monitor_geometry (screen, wsw->monitor_num, &monitor); + x = monitor.x + (monitor.width - event->width) / 2; + y = monitor.y + (monitor.height - event->height) / 2; + gtk_window_move (window, x, y); + + wsw->width = event->width; + wsw->height = event->height; + + return FALSE; +} + +static void +wswin_widget_class_init (WswinWidgetClass *klass) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); +} + +static GdkColor * +get_color (GtkWidget *win, GtkStateType state_type) +{ + GtkStyle *style; + + g_return_val_if_fail (win != NULL, NULL); + g_return_val_if_fail (GTK_IS_WIDGET (win), NULL); + g_return_val_if_fail (GTK_WIDGET_REALIZED (win), NULL); + + style = gtk_rc_get_style (win); + if (!style) + { + style = gtk_widget_get_style (win); + } + if (!style) + { + style = gtk_widget_get_default_style (); + } + + return (&style->bg[state_type]); +} + +static void +wswinDraw (WswinWidget *wsw) +{ + GdkScreen *screen; + cairo_t *cr; + Wswin *wswin = wsw->wswin; + GdkColor *bg_normal = get_color(GTK_WIDGET (wsw), GTK_STATE_NORMAL); + GdkColor *bg_selected = get_color(GTK_WIDGET (wsw), GTK_STATE_SELECTED); + gdouble width = GTK_WIDGET(wsw)->allocation.width; + gdouble height = GTK_WIDGET(wsw)->allocation.height; + gdouble x_size = width / wswin->cols; + gdouble y_size = height / wswin->rows; + gint border_radius = WIN_BORDER_RADIUS; + gdouble border_alpha = WIN_BORDER_ALPHA; + gdouble alpha = WIN_ALPHA; + gdouble degrees = 3.14 / 180.0; + gboolean composited; + gint row, col, current; + + if (!(wsw->exposed)) + return; + + cr = gdk_cairo_create (GTK_WIDGET(wsw)->window); + if (G_UNLIKELY (cr == NULL)) + return; + + screen = gtk_widget_get_screen(GTK_WIDGET(wsw)); + composited = gdk_screen_is_composited(screen); + + cairo_set_line_width (cr, 1); + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); + /* TODO: use workspaces.c style workspaceGetPosition so that we respect freedestop.org's layout stuff */ + /* TODO: creawte a workspace widget for each individual workspace so that they can be redrawn individually (more efficent and modular) */ + for(row = 0; row < wswin->rows; row++) + { + for(col = 0; col < wswin->cols; col++) + { + current = (row * wswin->cols) + col; + if(current >= wswin->count) + continue; + + /* only draw if we are the current or previous work space + draw no matter what if we are not yet drawn + if((wsw->undrawn == FALSE) && (current != wswin->selected) && (current != wswin->previous)) + continue; */ + + /* Draw a filled rounded rectangle with an outline */ + gint top, bot, left, right; + top = row*y_size+5; + bot = (row+1)*y_size-5; + left = col*x_size+5; + right = (col+1)*x_size-5; + + cairo_arc (cr, right - border_radius - 0.5, top + border_radius + 0.5, border_radius, -90 * degrees, 0 * degrees); + cairo_arc (cr, right - border_radius - 0.5, bot - border_radius - 0.5, border_radius, 0 * degrees, 90 * degrees); + cairo_arc (cr, left + border_radius + 0.5, bot - border_radius - 0.5, border_radius, 90 * degrees, 180 * degrees); + cairo_arc (cr, left + border_radius + 0.5, top + border_radius + 0.5, border_radius, 180 * degrees, 270 * degrees); + cairo_close_path(cr); + + if(composited) + cairo_set_source_rgba (cr, bg_selected->red/65535.0, bg_selected->green/65535.0, bg_selected->blue/65535.0, border_alpha); + else + gdk_cairo_set_source_color(cr, bg_normal); + + if(current == wswin->selected) + gdk_cairo_set_source_color(cr, bg_selected); + cairo_fill_preserve (cr); + gdk_cairo_set_source_color(cr, bg_selected); + cairo_stroke (cr); + } + } + + cairo_destroy (cr); + + wsw->undrawn = FALSE; +} + +static gboolean +wswin_expose (GtkWidget *wsw, GdkEventExpose *event, gpointer data) +{ + WswinWidget *wswin; + GdkScreen *screen; + cairo_t *cr; + GdkColor *bg_normal = get_color(wsw, GTK_STATE_NORMAL); + GdkColor *bg_selected = get_color(wsw, GTK_STATE_SELECTED); + gdouble width = wsw->allocation.width; + gdouble height = wsw->allocation.height; + gdouble border_alpha = WIN_BORDER_ALPHA; + gdouble alpha = WIN_ALPHA; + gint border_radius = WIN_BORDER_RADIUS; + gdouble degrees = 3.14 / 180.0; + + screen = gtk_widget_get_screen(GTK_WIDGET(wsw)); + cr = gdk_cairo_create (wsw->window); + if (G_UNLIKELY (cr == NULL)) + return FALSE; + + wswin = (WswinWidget *) data; + + cairo_set_line_width (cr, 1); + + if (gdk_screen_is_composited(screen)) { + cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); + gdk_cairo_region(cr, event->region); + cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.0); + cairo_fill_preserve(cr); + cairo_clip(cr); + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); + + /* Draw a filled rounded rectangle with an outline */ + cairo_arc (cr, width - border_radius - 0.5, border_radius + 0.5, border_radius, -90 * degrees, 0 * degrees); + cairo_arc (cr, width - border_radius - 0.5, height - border_radius - 0.5, border_radius, 0 * degrees, 90 * degrees); + cairo_arc (cr, border_radius + 0.5, height - border_radius - 0.5, border_radius, 90 * degrees, 180 * degrees); + cairo_arc (cr, border_radius + 0.5, border_radius + 0.5, border_radius, 180 * degrees, 270 * degrees); + cairo_close_path(cr); + gdk_cairo_set_source_color(cr, bg_normal); + //cairo_set_source_rgba (cr, bg_normal->red/65535.0, bg_normal->green/65535.0, bg_normal->blue/65535.0, alpha); + cairo_fill_preserve (cr); + gdk_cairo_set_source_color(cr, bg_selected); + //cairo_set_source_rgba (cr, bg_selected->red/65535.0, bg_selected->green/65535.0, bg_selected->blue/65535.0, border_alpha); + cairo_stroke (cr); + } + else{ + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); + cairo_rectangle(cr, 0, 0, width, height); + gdk_cairo_set_source_color(cr, bg_normal); + cairo_fill_preserve (cr); + gdk_cairo_set_source_color(cr, bg_selected); + cairo_stroke (cr); + } + + cairo_destroy (cr); + + wswin->exposed = TRUE; + + wswinDraw(wswin); + + return FALSE; +} + +static WswinWidget * +wswinCreateWidget (Wswin *wswin, ScreenInfo *screen_info, gint monitor_num) +{ + WswinWidget *wsw; + GdkScreen *screen; + GdkRectangle monitor; + + wsw = g_object_new(wswin_widget_get_type(), "type", GTK_WINDOW_POPUP, NULL); + + wsw->width = -1; + wsw->height = -1; + wsw->monitor_num = monitor_num; + wsw->wswin = wswin; + wsw->undrawn = TRUE; + wsw->exposed = FALSE; + + gtk_window_set_screen (GTK_WINDOW (wsw), screen_info->gscr); + /* TODO: give this its own name like "xfwm4-wswin" */ + /* for now we leave it the same for compatibility with themes */ + gtk_widget_set_name (GTK_WIDGET (wsw), "xfwm4-tabwin"); + + /* Check for compositing and set colormap for it */ + screen = gtk_widget_get_screen(GTK_WIDGET(wsw)); + if(gdk_screen_is_composited(screen)) { + GdkColormap *cmap = gdk_screen_get_rgba_colormap(screen); + if(cmap) + gtk_widget_set_colormap(GTK_WIDGET(wsw), cmap); + } + + gtk_widget_realize (GTK_WIDGET (wsw)); + gtk_container_set_border_width (GTK_CONTAINER (wsw), 4); + gtk_widget_set_app_paintable(GTK_WIDGET(wsw), TRUE); + gtk_window_set_position (GTK_WINDOW (wsw), GTK_WIN_POS_NONE); + gdk_screen_get_monitor_geometry (screen_info->gscr, wsw->monitor_num, &monitor); + gtk_window_move (GTK_WINDOW(wsw), monitor.x + monitor.width / 2, + monitor.y + monitor.height / 2); + /* TODO: set the size to be a param */ + gtk_window_set_default_size(GTK_WINDOW(wsw), 64*3*(wswin->cols), 40*3*(wswin->rows)); + + g_signal_connect_swapped (wsw, "configure-event", + GTK_SIGNAL_FUNC (wswinConfigure), (gpointer) wsw); + g_signal_connect (wsw, "expose-event", GTK_SIGNAL_FUNC (wswin_expose), (gpointer) wsw); + + gtk_widget_show_all(GTK_WIDGET(wsw)); + + return wsw; +} + +void +wswinSetSelected (Wswin *wswin, gint new_ws) +{ + GList *wswin_list; + WswinWidget *wsw; + + g_return_if_fail ( wswin != NULL ); + + /* Param checking */ + if ( (wswin->selected != new_ws) && (new_ws < (wswin->count)) ) + { + wswin->previous = wswin->selected; + wswin->selected = new_ws; + } + else + return; + + for(wswin_list = wswin->wswin_list; wswin_list; wswin_list = g_list_next (wswin_list)) + { + wsw = (WswinWidget *) wswin_list->data; + if(new_ws < (wswin->count)) + { + //wswinDraw(wsw); + gtk_widget_queue_draw (GTK_WIDGET(wsw)); + } + } + +} + +Wswin * +wswinCreate (ScreenInfo *screen_info) +{ + Wswin *wswin; + int num_monitors, i; + + g_return_val_if_fail (screen_info, NULL); + + TRACE ("entering wswinCreate"); + wswin = g_new0(Wswin, 1); + wswin->wswin_list = NULL; + wswin->rows = screen_info->desktop_layout.rows; + wswin->cols = screen_info->desktop_layout.cols; + wswin->count = screen_info->workspace_count; + wswin->selected = screen_info->current_ws; + wswin->previous = wswin->selected; + num_monitors = myScreenGetNumMonitors (screen_info); + for (i = 0; i < num_monitors; i++) + { + gint monitor_index; + + monitor_index = myScreenGetMonitorIndex(screen_info, i); + wswin->wswin_list = g_list_append(wswin->wswin_list, wswinCreateWidget(wswin, screen_info, monitor_index)); + } + + return wswin; +} + +void +wswinDestroy (Wswin *w) +{ + GList *wswin_list; + WswinWidget *wsw; + + g_return_if_fail (w != NULL); + TRACE ("entering wswinDestroy"); + + g_return_if_fail (w != NULL); + for (wswin_list = w->wswin_list; wswin_list; wswin_list = g_list_next (wswin_list)) + { + wsw = (WswinWidget *) wswin_list->data; + g_list_free (wsw->widgets); + gtk_widget_destroy (GTK_WIDGET (wsw)); + } + g_list_free (w->wswin_list); +} + diff --git a/src/workspacewin.h b/src/workspacewin.h new file mode 100644 index 0000000..d4aa199 --- /dev/null +++ b/src/workspacewin.h @@ -0,0 +1,76 @@ +/* $Id$ + + 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. + + + xfwm4 - (c) 2002-2011 Olivier Fourdan + + */ + +#ifndef INC_WORKSPACEWIN_H +#define INC_WORKSPACEWIN_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include "focus.h" + +typedef struct _Wswin Wswin; +typedef struct _WswinWidget WswinWidget; +typedef struct _WswinWidgetClass WswinWidgetClass; + +struct _Wswin +{ + GList *wswin_list; + gint cols; + gint rows; + gint count; + gint selected; + gint previous; +}; + +struct _WswinWidget +{ + GtkWindow __parent__; + /* The below must be freed when destroying */ + GList *widgets; + + /* these don't have to be */ + Wswin *wswin; + GtkWidget *class; + GtkWidget *label; + GtkWidget *container; + + gint width, height; + gboolean undrawn; + gboolean exposed; + gint monitor_num; +}; + +struct _WswinWidgetClass +{ + GtkWindowClass __parent__; +}; + +Wswin *wswinCreate (ScreenInfo *); +void wswinDestroy (Wswin *); +void wswinSetSelected (Wswin *, gint); + +#endif /* INC_WORKSPACEWIN_H */ -- 2.1.4