Merge lp:~jassmith/window-picker-applet/task-item-rewrite into lp:window-picker-applet
- task-item-rewrite
- Merge into trunk
| Status: | Merged |
|---|---|
| Merged at revision: | not available |
| Proposed branch: | lp:~jassmith/window-picker-applet/task-item-rewrite |
| Merge into: | lp:window-picker-applet |
| Diff against target: | None lines |
| To merge this branch: | bzr merge lp:~jassmith/window-picker-applet/task-item-rewrite |
| Related bugs: |
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| Neil J. Patel (community) | Needs Fixing | ||
|
Review via email:
|
|||
Commit message
Description of the change
| Jason Smith (jassmith) wrote : | # |
- 99. By Jason Smith <jason@t500>
-
modified:
src/task-item.c : Added prelighting to buttons
| Neil J. Patel (njpatel) wrote : | # |
Nice job! Love the fading animation when window has the urgent hint, and definitely like the clean-up fo the code.
There are a couple of things I noticed that need to be fixed before merge:
- The icons no-longer pickup the colour of the panel if it's different from the standard Gtk colour (i.e. when using right-click-
- The 1px click-through area the top of the icons seems to effect the entire applet, so maybe the container border needs to be removed from the the main box thats holding the applet's content.
-- Below is not merge-critical as we can fix after feature freeze --:
- Using it for some time on a netbook, I don't think there's enough difference between an active window's icon and a non-active window's icon. We should try a hi-light behind the active icon as before, or a glow/etc.
- 100. By Jason Smith <jason@t500>
-
Actually draw on parent window. oops.
Fixes bug where buttons would have black background in some situations. - 101. By Jason Smith <jason@t500>
-
Fix fitz law problem
| Jason Smith (jassmith) wrote : | # |
> Nice job! Love the fading animation when window has the urgent hint, and
> definitely like the clean-up fo the code.
>
> There are a couple of things I noticed that need to be fixed before merge:
>
> - The icons no-longer pickup the colour of the panel if it's different from
> the standard Gtk colour (i.e. when using right-click-
> and setting it to a different colour/changing transparency or setting a
> background image).
Fixed
>
> - The 1px click-through area the top of the icons seems to effect the entire
> applet, so maybe the container border needs to be removed from the the main
> box thats holding the applet's content.
Fixed AND grew the icons by 2px.
>
> -- Below is not merge-critical as we can fix after feature freeze --:
>
> - Using it for some time on a netbook, I don't think there's enough difference
> between an active window's icon and a non-active window's icon. We should try
> a hi-light behind the active icon as before, or a glow/etc.
Just let me know what you want. I will do a glow like effect and see if that helps. I will strive to make it very very obvious which one is active. We will need something other than what we had before however since in many cases, that wont be at all visible.
- 102. By Jason Smith <jason@t500>
-
task-item.c : fix render glitch, remember allocation
Preview Diff
| 1 | === modified file 'src/Makefile.am' |
| 2 | --- src/Makefile.am 2008-06-14 15:09:30 +0000 |
| 3 | +++ src/Makefile.am 2009-08-18 23:59:03 +0000 |
| 4 | @@ -16,6 +16,8 @@ |
| 5 | |
| 6 | window_picker_applet_SOURCES = \ |
| 7 | applet.c \ |
| 8 | + task-item.c \ |
| 9 | + task-item.h \ |
| 10 | task-list.c \ |
| 11 | task-list.h \ |
| 12 | task-title.c \ |
| 13 | |
| 14 | === added file 'src/task-item.c' |
| 15 | --- src/task-item.c 1970-01-01 00:00:00 +0000 |
| 16 | +++ src/task-item.c 2009-08-21 07:06:29 +0000 |
| 17 | @@ -0,0 +1,633 @@ |
| 18 | +/* |
| 19 | + * Copyright (C) 2008 Canonical Ltd |
| 20 | + * |
| 21 | + * This program is free software: you can redistribute it and/or modify |
| 22 | + * it under the terms of the GNU General Public License version 3 as |
| 23 | + * published by the Free Software Foundation. |
| 24 | + * |
| 25 | + * This program is distributed in the hope that it will be useful, |
| 26 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 27 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 28 | + * GNU General Public License for more details. |
| 29 | + * |
| 30 | + * You should have received a copy of the GNU General Public License |
| 31 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 32 | + * |
| 33 | + * Authored by Jason Smith <jassmith@gmail.com> |
| 34 | + * |
| 35 | + */ |
| 36 | + |
| 37 | +#include "task-item.h" |
| 38 | +#include "task-list.h" |
| 39 | + |
| 40 | +#include <math.h> |
| 41 | +#include <cairo/cairo.h> |
| 42 | + |
| 43 | +G_DEFINE_TYPE (TaskItem, task_item, GTK_TYPE_EVENT_BOX); |
| 44 | + |
| 45 | +#define TASK_ITEM_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\ |
| 46 | + TASK_TYPE_ITEM, \ |
| 47 | + TaskItemPrivate)) |
| 48 | + |
| 49 | +#define DEFAULT_TASK_ITEM_HEIGHT 24; |
| 50 | +#define DEFAULT_TASK_ITEM_WIDTH 28 |
| 51 | + |
| 52 | +struct _TaskItemPrivate |
| 53 | +{ |
| 54 | + WnckWindow *window; |
| 55 | + WnckScreen *screen; |
| 56 | + GdkPixbuf *pixbuf; |
| 57 | + |
| 58 | + GTimeVal urgent_time; |
| 59 | + guint timer; |
| 60 | +}; |
| 61 | + |
| 62 | +enum { |
| 63 | + TASK_ITEM_CLOSED_SIGNAL, |
| 64 | + LAST_SIGNAL |
| 65 | +}; |
| 66 | + |
| 67 | +/* D&D stuff */ |
| 68 | +static const GtkTargetEntry drop_types[] = |
| 69 | +{ |
| 70 | + { "STRING", 0, 0 }, |
| 71 | + { "text/plain", 0, 0}, |
| 72 | + { "text/uri-list", 0, 0} |
| 73 | +}; |
| 74 | +static const gint n_drop_types = G_N_ELEMENTS(drop_types); |
| 75 | + |
| 76 | +static guint task_item_signals[LAST_SIGNAL] = { 0 }; |
| 77 | + |
| 78 | +static void |
| 79 | +update_hints (TaskItem *item) |
| 80 | +{ |
| 81 | + GtkWidget *parent; |
| 82 | + GtkWidget *widget; |
| 83 | + WnckWindow *window; |
| 84 | + gint x, y, x1, y1; |
| 85 | + |
| 86 | + widget = GTK_WIDGET (item); |
| 87 | + window = item->priv->window; |
| 88 | + /* Skip problems */ |
| 89 | + if (!WNCK_IS_WINDOW (window)) return; |
| 90 | + if (!GTK_IS_WIDGET (widget)) return; |
| 91 | + |
| 92 | + /* Skip invisible windows */ |
| 93 | + if (!GTK_WIDGET_VISIBLE (widget)) return; |
| 94 | + |
| 95 | + x = y = 0; |
| 96 | + |
| 97 | + /* Recursively compute the button's coordinates */ |
| 98 | + for (parent = widget; parent; parent = parent->parent) |
| 99 | + { |
| 100 | + if (parent->parent) |
| 101 | + { |
| 102 | + x += parent->allocation.x; |
| 103 | + y += parent->allocation.y; |
| 104 | + } |
| 105 | + else |
| 106 | + { |
| 107 | + x1 = y1 = 0; |
| 108 | + if (GDK_IS_WINDOW (parent->window)) |
| 109 | + gdk_window_get_origin (parent->window, &x1, &y1); |
| 110 | + x += x1; y += y1; |
| 111 | + break; |
| 112 | + } |
| 113 | + } |
| 114 | + |
| 115 | + /* Set the minimize hint for the window */ |
| 116 | + wnck_window_set_icon_geometry (window, x, y, |
| 117 | + widget->allocation.width, |
| 118 | + widget->allocation.height); |
| 119 | +} |
| 120 | + |
| 121 | +static gboolean |
| 122 | +on_task_item_button_released (GtkWidget *widget, |
| 123 | + GdkEventButton *event, |
| 124 | + TaskItem *item) |
| 125 | +{ |
| 126 | + WnckWindow *window; |
| 127 | + WnckScreen *screen; |
| 128 | + WnckWorkspace *workspace; |
| 129 | + TaskItemPrivate *priv; |
| 130 | + |
| 131 | + g_return_val_if_fail (TASK_IS_ITEM (item), TRUE); |
| 132 | + |
| 133 | + priv = item->priv; |
| 134 | + window = priv->window; |
| 135 | + |
| 136 | + g_return_val_if_fail (WNCK_IS_WINDOW (window), TRUE); |
| 137 | + |
| 138 | + screen = priv->screen; |
| 139 | + workspace = wnck_window_get_workspace (window); |
| 140 | + |
| 141 | + if (event->button == 1) |
| 142 | + { |
| 143 | + |
| 144 | + if (WNCK_IS_WORKSPACE (workspace) && workspace != wnck_screen_get_active_workspace (screen)) |
| 145 | + { |
| 146 | + wnck_workspace_activate (workspace, GDK_CURRENT_TIME); |
| 147 | + } |
| 148 | + if (wnck_window_is_active (window)) |
| 149 | + { |
| 150 | + wnck_window_minimize (window); |
| 151 | + } |
| 152 | + else |
| 153 | + { |
| 154 | + wnck_window_activate (window, GDK_CURRENT_TIME); |
| 155 | + } |
| 156 | + } |
| 157 | + return TRUE; |
| 158 | +} |
| 159 | + |
| 160 | +static void |
| 161 | +task_item_set_visibility (TaskItem *item) |
| 162 | +{ |
| 163 | + WnckScreen *screen; |
| 164 | + WnckWindow *window; |
| 165 | + WnckWorkspace *workspace; |
| 166 | + |
| 167 | + g_return_if_fail (TASK_IS_ITEM (item)); |
| 168 | + |
| 169 | + TaskItemPrivate *priv = item->priv; |
| 170 | + |
| 171 | + if (!WNCK_IS_WINDOW (priv->window)) |
| 172 | + { |
| 173 | + gtk_widget_hide (GTK_WIDGET (item)); |
| 174 | + return; |
| 175 | + } |
| 176 | + |
| 177 | + window = priv->window; |
| 178 | + |
| 179 | + screen = priv->screen; |
| 180 | + workspace = wnck_screen_get_active_workspace (screen); |
| 181 | + |
| 182 | + gboolean show_all = task_list_get_show_all_windows (TASK_LIST (task_list_get_default ())); |
| 183 | + |
| 184 | + if (wnck_window_is_skip_tasklist (window) || |
| 185 | + (!show_all && !wnck_window_is_on_workspace (window, workspace))) |
| 186 | + { |
| 187 | + gtk_widget_hide (GTK_WIDGET (item)); |
| 188 | + } |
| 189 | + else |
| 190 | + { |
| 191 | + gtk_widget_show (GTK_WIDGET (item)); |
| 192 | + } |
| 193 | +} |
| 194 | + |
| 195 | +static void |
| 196 | +task_item_size_request (GtkWidget *widget, |
| 197 | + GtkRequisition *requisition) |
| 198 | +{ |
| 199 | + /* Candidate for terrible hack of the year award */ |
| 200 | + requisition->width = DEFAULT_TASK_ITEM_WIDTH; |
| 201 | + requisition->height = DEFAULT_TASK_ITEM_HEIGHT; |
| 202 | +} |
| 203 | + |
| 204 | +static GdkPixbuf * |
| 205 | +task_item_sized_pixbuf_for_window (TaskItem *item, |
| 206 | + WnckWindow *window, |
| 207 | + gint size) |
| 208 | +{ |
| 209 | + GdkPixbuf *pbuf; |
| 210 | + |
| 211 | + g_return_val_if_fail (WNCK_IS_WINDOW (window), NULL); |
| 212 | + |
| 213 | + if (wnck_window_has_icon_name (window)) |
| 214 | + { |
| 215 | + const gchar *icon_name = wnck_window_get_icon_name (window); |
| 216 | + GtkIconTheme *icon_theme = gtk_icon_theme_get_default (); |
| 217 | + |
| 218 | + if (gtk_icon_theme_has_icon (icon_theme, icon_name)) |
| 219 | + { |
| 220 | + |
| 221 | + pbuf = gdk_pixbuf_copy (gtk_icon_theme_load_icon (icon_theme, |
| 222 | + icon_name, |
| 223 | + size, |
| 224 | + GTK_ICON_LOOKUP_FORCE_SIZE, |
| 225 | + NULL)); |
| 226 | + } |
| 227 | + } |
| 228 | + |
| 229 | + if (!pbuf) |
| 230 | + { |
| 231 | + pbuf = gdk_pixbuf_copy (wnck_window_get_icon (item->priv->window)); |
| 232 | + } |
| 233 | + |
| 234 | + gint width = gdk_pixbuf_get_width (pbuf); |
| 235 | + gint height = gdk_pixbuf_get_height (pbuf); |
| 236 | + |
| 237 | + if (width > size || height > size) |
| 238 | + { |
| 239 | + gdouble scale; |
| 240 | + if (width > size) |
| 241 | + { |
| 242 | + scale = (gdouble) size / (gdouble) width; |
| 243 | + width = size; |
| 244 | + height = (int) (height * scale); |
| 245 | + } |
| 246 | + if (height > size) |
| 247 | + { |
| 248 | + scale = (gdouble) size / (gdouble) height; |
| 249 | + height = size; |
| 250 | + width = (int) (width * scale); |
| 251 | + } |
| 252 | + |
| 253 | + GdkPixbuf *tmp = pbuf; |
| 254 | + pbuf = gdk_pixbuf_scale_simple (tmp, width, height, GDK_INTERP_HYPER); |
| 255 | + |
| 256 | + g_object_unref (tmp); |
| 257 | + } |
| 258 | + |
| 259 | + return pbuf; |
| 260 | +} |
| 261 | +static gboolean |
| 262 | +task_item_expose_event (GtkWidget *widget, |
| 263 | + GdkEventExpose *event) |
| 264 | +{ |
| 265 | + cairo_t *cr; |
| 266 | + TaskItem *item; |
| 267 | + GdkRectangle area; |
| 268 | + TaskItemPrivate *priv; |
| 269 | + |
| 270 | + g_return_val_if_fail (widget != NULL, FALSE); |
| 271 | + g_return_val_if_fail (TASK_IS_ITEM (widget), FALSE); |
| 272 | + g_return_val_if_fail (event != NULL, FALSE); |
| 273 | + |
| 274 | + if (event->count > 0) |
| 275 | + return FALSE; |
| 276 | + |
| 277 | + item = TASK_ITEM (widget); |
| 278 | + priv = item->priv; |
| 279 | + |
| 280 | + g_return_val_if_fail (WNCK_IS_WINDOW (item->priv->window), FALSE); |
| 281 | + |
| 282 | + area = event->area; |
| 283 | + cr = gdk_cairo_create (event->window); |
| 284 | + |
| 285 | + GdkPixbuf *pbuf = priv->pixbuf; |
| 286 | + |
| 287 | + gint size = MIN (area.height, area.width); |
| 288 | + |
| 289 | + if (GDK_IS_PIXBUF (pbuf) && (gdk_pixbuf_get_width (pbuf) > size || |
| 290 | + gdk_pixbuf_get_height (pbuf) > size)) |
| 291 | + { |
| 292 | + g_object_unref (pbuf); |
| 293 | + pbuf = NULL; |
| 294 | + } |
| 295 | + |
| 296 | + if (!pbuf) |
| 297 | + { |
| 298 | + pbuf = task_item_sized_pixbuf_for_window (item, priv->window, size); |
| 299 | + } |
| 300 | + |
| 301 | + gdk_cairo_set_source_pixbuf (cr, |
| 302 | + pbuf, |
| 303 | + (area.width - gdk_pixbuf_get_width (pbuf)) / 2, |
| 304 | + (area.height - gdk_pixbuf_get_height (pbuf)) / 2); |
| 305 | + |
| 306 | + g_object_unref (pbuf); |
| 307 | + |
| 308 | + if (wnck_window_or_transient_needs_attention (priv->window)) |
| 309 | + { |
| 310 | + GTimeVal current_time; |
| 311 | + g_get_current_time (¤t_time); |
| 312 | + |
| 313 | + gdouble ms = (current_time.tv_sec - priv->urgent_time.tv_sec) * 1000 + |
| 314 | + (current_time.tv_usec - priv->urgent_time.tv_usec) / 1000; |
| 315 | + |
| 316 | + gdouble alpha = .75 + (cos (ms / 500) / 4); |
| 317 | + cairo_paint_with_alpha (cr, alpha); |
| 318 | + } |
| 319 | + else if (wnck_window_is_active (priv->window)) |
| 320 | + { |
| 321 | + cairo_paint (cr); |
| 322 | + } |
| 323 | + else |
| 324 | + { |
| 325 | + cairo_paint_with_alpha (cr, .6); |
| 326 | + } |
| 327 | + |
| 328 | + cairo_destroy (cr); |
| 329 | + |
| 330 | + return FALSE; |
| 331 | +} |
| 332 | + |
| 333 | +static void |
| 334 | +on_size_allocate (GtkWidget *widget, |
| 335 | + GtkAllocation *allocation, |
| 336 | + TaskItem *item) |
| 337 | +{ |
| 338 | + if (allocation->width != allocation->height) |
| 339 | + gtk_widget_set_size_request (widget, allocation->height, -1); |
| 340 | + |
| 341 | + update_hints (item); |
| 342 | +} |
| 343 | + |
| 344 | +static gboolean |
| 345 | +on_button_pressed (GtkWidget *button, |
| 346 | + GdkEventButton *event, |
| 347 | + TaskItem *item) |
| 348 | +{ |
| 349 | + WnckWindow *window; |
| 350 | + g_return_val_if_fail (TASK_IS_ITEM (item), FALSE); |
| 351 | + window = item->priv->window; |
| 352 | + g_return_val_if_fail (WNCK_IS_WINDOW (window), FALSE); |
| 353 | + |
| 354 | + if (event->button == 3) |
| 355 | + { |
| 356 | + GtkWidget *menu = wnck_action_menu_new (window); |
| 357 | + gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, |
| 358 | + event->button, event->time); |
| 359 | + return TRUE; |
| 360 | + } |
| 361 | + |
| 362 | + return FALSE; |
| 363 | +} |
| 364 | + |
| 365 | +static gboolean |
| 366 | +on_query_tooltip (GtkWidget *widget, |
| 367 | + gint x, gint y, |
| 368 | + gboolean keyboard_mode, |
| 369 | + GtkTooltip *tooltip, |
| 370 | + TaskItem *item) |
| 371 | +{ |
| 372 | + WnckWindow *window = item->priv->window; |
| 373 | + g_return_val_if_fail (WNCK_IS_WINDOW (window), FALSE); |
| 374 | + |
| 375 | + gtk_tooltip_set_text (tooltip, wnck_window_get_name(window)); |
| 376 | + gtk_tooltip_set_icon (tooltip, wnck_window_get_icon (window)); |
| 377 | + |
| 378 | + return TRUE; |
| 379 | +} |
| 380 | + |
| 381 | +static gboolean |
| 382 | +on_blink (TaskItem *item) |
| 383 | +{ |
| 384 | + g_return_val_if_fail (TASK_IS_ITEM (item), FALSE); |
| 385 | + |
| 386 | + gtk_widget_queue_draw (GTK_WIDGET (item)); |
| 387 | + |
| 388 | + if (wnck_window_or_transient_needs_attention (item->priv->window)) |
| 389 | + { |
| 390 | + return TRUE; |
| 391 | + } |
| 392 | + else |
| 393 | + { |
| 394 | + item->priv->timer = 0; |
| 395 | + return FALSE; |
| 396 | + } |
| 397 | +} |
| 398 | + |
| 399 | +static void |
| 400 | +on_window_state_changed (WnckWindow *window, |
| 401 | + WnckWindowState changed_mask, |
| 402 | + WnckWindowState new_state, |
| 403 | + TaskItem *item) |
| 404 | +{ |
| 405 | + g_return_if_fail (WNCK_IS_WINDOW (window)); |
| 406 | + g_return_if_fail (TASK_IS_ITEM (item)); |
| 407 | + |
| 408 | + TaskItemPrivate *priv = item->priv; |
| 409 | + |
| 410 | + if (new_state & WNCK_WINDOW_STATE_URGENT && !priv->timer) |
| 411 | + { |
| 412 | + priv->timer = g_timeout_add (30, (GSourceFunc)on_blink, item); |
| 413 | + g_get_current_time (&priv->urgent_time); |
| 414 | + } |
| 415 | + |
| 416 | + task_item_set_visibility (item); |
| 417 | +} |
| 418 | + |
| 419 | +static void |
| 420 | +on_window_workspace_changed (WnckWindow *window, TaskItem *item) |
| 421 | +{ |
| 422 | + g_return_if_fail (TASK_IS_ITEM (item)); |
| 423 | + |
| 424 | + task_item_set_visibility (item); |
| 425 | +} |
| 426 | + |
| 427 | +static void |
| 428 | +on_screen_active_window_changed (WnckScreen *screen, |
| 429 | + WnckWindow *old_window, |
| 430 | + TaskItem *item) |
| 431 | +{ |
| 432 | + WnckWindow *window; |
| 433 | + TaskItemPrivate *priv; |
| 434 | + |
| 435 | + g_return_if_fail (TASK_IS_ITEM (item)); |
| 436 | + |
| 437 | + priv = item->priv; |
| 438 | + window = priv->window; |
| 439 | + |
| 440 | + g_return_if_fail (WNCK_IS_WINDOW (window)); |
| 441 | + |
| 442 | + if ((WNCK_IS_WINDOW (old_window) && window == old_window) || |
| 443 | + window == wnck_screen_get_active_window (screen)) |
| 444 | + { |
| 445 | + /* queue a draw to reflect that we are [no longer] the active window */ |
| 446 | + gtk_widget_queue_draw (GTK_WIDGET (item)); |
| 447 | + } |
| 448 | +} |
| 449 | + |
| 450 | +static void |
| 451 | +on_screen_active_workspace_changed (WnckScreen *screen, |
| 452 | + WnckWorkspace *old_workspace, |
| 453 | + TaskItem *item) |
| 454 | +{ |
| 455 | + g_return_if_fail (TASK_IS_ITEM (item)); |
| 456 | + |
| 457 | + task_item_set_visibility (item); |
| 458 | +} |
| 459 | + |
| 460 | +static void |
| 461 | +on_screen_active_viewport_changed (WnckScreen *screen, |
| 462 | + TaskItem *item) |
| 463 | +{ |
| 464 | + g_return_if_fail (TASK_IS_ITEM (item)); |
| 465 | + |
| 466 | + task_item_set_visibility (item); |
| 467 | +} |
| 468 | + |
| 469 | +static void |
| 470 | +on_screen_window_closed (WnckScreen *screen, |
| 471 | + WnckWindow *window, |
| 472 | + TaskItem *item) |
| 473 | +{ |
| 474 | + TaskItemPrivate *priv; |
| 475 | + |
| 476 | + g_return_if_fail (TASK_IS_ITEM (item)); |
| 477 | + priv = item->priv; |
| 478 | + g_return_if_fail (WNCK_IS_WINDOW (priv->window)); |
| 479 | + |
| 480 | + if (priv->window == window) |
| 481 | + { |
| 482 | + g_signal_handlers_disconnect_by_func (screen, G_CALLBACK (on_screen_window_closed), item); |
| 483 | + g_signal_handlers_disconnect_by_func (screen, G_CALLBACK (on_screen_active_window_changed), item); |
| 484 | + g_signal_handlers_disconnect_by_func (screen, G_CALLBACK (on_screen_active_workspace_changed), item); |
| 485 | + g_signal_handlers_disconnect_by_func (screen, G_CALLBACK (on_screen_window_closed), item); |
| 486 | + g_signal_handlers_disconnect_by_func (window, G_CALLBACK (on_window_workspace_changed), item); |
| 487 | + g_signal_handlers_disconnect_by_func (window, G_CALLBACK (on_window_state_changed), item); |
| 488 | + |
| 489 | + g_signal_emit (G_OBJECT (item), task_item_signals[TASK_ITEM_CLOSED_SIGNAL], 0); |
| 490 | + } |
| 491 | +} |
| 492 | + |
| 493 | +static gboolean |
| 494 | +activate_window (GtkWidget *widget) |
| 495 | +{ |
| 496 | + gint active; |
| 497 | + |
| 498 | + g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); |
| 499 | + |
| 500 | + active = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "drag-true")); |
| 501 | + |
| 502 | + if (active) |
| 503 | + { |
| 504 | + WnckWindow *window; |
| 505 | + |
| 506 | + window = (WnckWindow*)g_object_get_data (G_OBJECT (widget), "WnckWindow"); |
| 507 | + if (WNCK_IS_WINDOW (window)) |
| 508 | + wnck_window_activate (window, time (NULL)); |
| 509 | + } |
| 510 | + |
| 511 | + g_object_set_data (G_OBJECT (widget), "drag-true", GINT_TO_POINTER (0)); |
| 512 | + |
| 513 | + return FALSE; |
| 514 | +} |
| 515 | + |
| 516 | +static void |
| 517 | +on_drag_leave (GtkWidget *item, |
| 518 | + GdkDragContext *context, |
| 519 | + guint time) |
| 520 | +{ |
| 521 | + g_object_set_data (G_OBJECT (item), "drag-true", GINT_TO_POINTER (0)); |
| 522 | +} |
| 523 | + |
| 524 | +static gboolean |
| 525 | +on_drag_motion (GtkWidget *item, |
| 526 | + GdkDragContext *context, |
| 527 | + gint x, |
| 528 | + gint y, |
| 529 | + guint t) |
| 530 | +{ |
| 531 | + gint active; |
| 532 | + |
| 533 | + active = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item), "drag-true")); |
| 534 | + |
| 535 | + if (!active) |
| 536 | + { |
| 537 | + g_object_set_data (G_OBJECT (item), "drag-true", GINT_TO_POINTER (1)); |
| 538 | + |
| 539 | + g_timeout_add (1000, (GSourceFunc)activate_window, item); |
| 540 | + } |
| 541 | + |
| 542 | + return FALSE; |
| 543 | +} |
| 544 | + |
| 545 | +static void |
| 546 | +task_item_finalize (GObject *object) |
| 547 | +{ |
| 548 | + TaskItemPrivate *priv; |
| 549 | + priv = TASK_ITEM_GET_PRIVATE (object); |
| 550 | + |
| 551 | + /* remove timer */ |
| 552 | + if (priv->timer) g_source_remove (priv->timer); |
| 553 | + |
| 554 | + G_OBJECT_CLASS (task_item_parent_class)->finalize (object); |
| 555 | +} |
| 556 | + |
| 557 | +static void |
| 558 | +task_item_class_init (TaskItemClass *klass) |
| 559 | +{ |
| 560 | + GObjectClass *obj_class = G_OBJECT_CLASS (klass); |
| 561 | + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); |
| 562 | + |
| 563 | + obj_class->finalize = task_item_finalize; |
| 564 | + widget_class->expose_event = task_item_expose_event; |
| 565 | + widget_class->size_request = task_item_size_request; |
| 566 | + |
| 567 | + g_type_class_add_private (obj_class, sizeof (TaskItemPrivate)); |
| 568 | + |
| 569 | + task_item_signals [TASK_ITEM_CLOSED_SIGNAL] = |
| 570 | + g_signal_new ("task-item-closed", |
| 571 | + G_TYPE_FROM_CLASS (klass), |
| 572 | + G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, |
| 573 | + G_STRUCT_OFFSET (TaskItemClass, itemclosed), |
| 574 | + NULL, NULL, |
| 575 | + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); |
| 576 | +} |
| 577 | + |
| 578 | +static void |
| 579 | +task_item_init (TaskItem *item) |
| 580 | +{ |
| 581 | + TaskItemPrivate *priv; |
| 582 | + priv = item->priv = TASK_ITEM_GET_PRIVATE (item); |
| 583 | + |
| 584 | + priv->timer = 0; |
| 585 | +} |
| 586 | + |
| 587 | +GtkWidget * |
| 588 | +task_item_new (WnckWindow *window) |
| 589 | +{ |
| 590 | + GtkWidget *item = NULL; |
| 591 | + TaskItem *task; |
| 592 | + TaskItemPrivate *priv; |
| 593 | + WnckScreen *screen; |
| 594 | + |
| 595 | + g_return_val_if_fail (WNCK_IS_WINDOW (window), item); |
| 596 | + |
| 597 | + item = g_object_new (TASK_TYPE_ITEM, |
| 598 | + "has-tooltip", TRUE, |
| 599 | + "visible-window", TRUE, |
| 600 | + "above-child", TRUE, |
| 601 | + NULL); |
| 602 | + |
| 603 | + gtk_widget_add_events (item, GDK_ALL_EVENTS_MASK); |
| 604 | + gtk_container_set_border_width (GTK_CONTAINER (item), 0); |
| 605 | + |
| 606 | + task = TASK_ITEM (item); |
| 607 | + priv = task->priv; |
| 608 | + priv->window = window; |
| 609 | + |
| 610 | + screen = wnck_window_get_screen (window); |
| 611 | + priv->screen = screen; |
| 612 | + |
| 613 | + gtk_drag_dest_set (item, |
| 614 | + GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP, |
| 615 | + drop_types, n_drop_types, |
| 616 | + GDK_ACTION_COPY); |
| 617 | + gtk_drag_dest_add_uri_targets (item); |
| 618 | + gtk_drag_dest_add_text_targets (item); |
| 619 | + g_signal_connect (item, "drag-motion", |
| 620 | + G_CALLBACK (on_drag_motion), NULL); |
| 621 | + g_signal_connect (item, "drag-leave", |
| 622 | + G_CALLBACK (on_drag_leave), NULL); |
| 623 | + |
| 624 | + g_signal_connect (screen, "viewports-changed", |
| 625 | + G_CALLBACK (on_screen_active_viewport_changed), item); |
| 626 | + g_signal_connect (screen, "active-window-changed", |
| 627 | + G_CALLBACK (on_screen_active_window_changed), item); |
| 628 | + g_signal_connect (screen, "active-workspace-changed", |
| 629 | + G_CALLBACK (on_screen_active_workspace_changed), item); |
| 630 | + g_signal_connect (screen, "window-closed", |
| 631 | + G_CALLBACK (on_screen_window_closed), item); |
| 632 | + |
| 633 | + g_signal_connect (window, "workspace-changed", |
| 634 | + G_CALLBACK (on_window_workspace_changed), item); |
| 635 | + g_signal_connect (window, "state-changed", |
| 636 | + G_CALLBACK (on_window_state_changed), item); |
| 637 | + |
| 638 | + g_signal_connect (item, "button-release-event", |
| 639 | + G_CALLBACK (on_task_item_button_released), item); |
| 640 | + g_signal_connect (item, "button-press-event", |
| 641 | + G_CALLBACK (on_button_pressed), item); |
| 642 | + g_signal_connect (item, "size-allocate", |
| 643 | + G_CALLBACK (on_size_allocate), item); |
| 644 | + g_signal_connect (item, "query-tooltip", |
| 645 | + G_CALLBACK (on_query_tooltip), item); |
| 646 | + |
| 647 | + task_item_set_visibility (task); |
| 648 | + |
| 649 | + return item; |
| 650 | +} |
| 651 | |
| 652 | === added file 'src/task-item.h' |
| 653 | --- src/task-item.h 1970-01-01 00:00:00 +0000 |
| 654 | +++ src/task-item.h 2009-08-20 23:49:02 +0000 |
| 655 | @@ -0,0 +1,72 @@ |
| 656 | +/* |
| 657 | + * Copyright (C) 2008 Canonical Ltd |
| 658 | + * |
| 659 | + * This program is free software: you can redistribute it and/or modify |
| 660 | + * it under the terms of the GNU General Public License version 3 as |
| 661 | + * published by the Free Software Foundation. |
| 662 | + * |
| 663 | + * This program is distributed in the hope that it will be useful, |
| 664 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 665 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 666 | + * GNU General Public License for more details. |
| 667 | + * |
| 668 | + * You should have received a copy of the GNU General Public License |
| 669 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 670 | + * |
| 671 | + * Authored by: Neil Jagdish Patel <neil.patel@canonical.com> |
| 672 | + * Jason Smith <jassmith@gmail.com> |
| 673 | + * |
| 674 | + */ |
| 675 | + |
| 676 | +#ifndef _TASK_ITEM_H_ |
| 677 | +#define _TASK_ITEM_H_ |
| 678 | + |
| 679 | +#include <glib.h> |
| 680 | +#include <gtk/gtk.h> |
| 681 | +#include <libwnck/libwnck.h> |
| 682 | + |
| 683 | +#define TASK_TYPE_ITEM (task_item_get_type ()) |
| 684 | + |
| 685 | +#define TASK_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),\ |
| 686 | + TASK_TYPE_ITEM, TaskItem)) |
| 687 | + |
| 688 | +#define TASK_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass),\ |
| 689 | + TASK_TYPE_ITEM, TaskItemClass)) |
| 690 | + |
| 691 | +#define TASK_IS_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\ |
| 692 | + TASK_TYPE_ITEM)) |
| 693 | + |
| 694 | +#define TASK_IS_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),\ |
| 695 | + TASK_TYPE_ITEM)) |
| 696 | + |
| 697 | +#define TASK_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),\ |
| 698 | + TASK_TYPE_ITEM, TaskItemClass)) |
| 699 | + |
| 700 | +typedef struct _TaskItem TaskItem; |
| 701 | +typedef struct _TaskItemClass TaskItemClass; |
| 702 | +typedef struct _TaskItemPrivate TaskItemPrivate; |
| 703 | + |
| 704 | +struct _TaskItem |
| 705 | +{ |
| 706 | + GtkEventBox parent; |
| 707 | + |
| 708 | + TaskItemPrivate *priv; |
| 709 | +}; |
| 710 | + |
| 711 | +struct _TaskItemClass |
| 712 | +{ |
| 713 | + GtkEventBoxClass parent_class; |
| 714 | + |
| 715 | + void (* itemclosed) (TaskItem *item); |
| 716 | +}; |
| 717 | + |
| 718 | +GType task_item_get_type (void) G_GNUC_CONST; |
| 719 | + |
| 720 | +GtkWidget * task_item_new (WnckWindow *window); |
| 721 | + |
| 722 | +GtkWidget * task_item_get_default (void); |
| 723 | + |
| 724 | +gboolean task_item_get_desktop_visible (TaskItem *item); |
| 725 | + |
| 726 | +#endif /* _TASK_ITEM_H_ */ |
| 727 | + |
| 728 | |
| 729 | === modified file 'src/task-list.c' |
| 730 | --- src/task-list.c 2009-04-08 10:19:27 +0000 |
| 731 | +++ src/task-list.c 2009-08-21 07:06:29 +0000 |
| 732 | @@ -18,6 +18,7 @@ |
| 733 | */ |
| 734 | |
| 735 | #include "task-list.h" |
| 736 | +#include "task-item.h" |
| 737 | |
| 738 | #include <libwnck/libwnck.h> |
| 739 | |
| 740 | @@ -44,109 +45,6 @@ |
| 741 | PROP_SHOW_ALL_WINDOWS |
| 742 | }; |
| 743 | |
| 744 | -/* D&D stuff */ |
| 745 | -static const GtkTargetEntry drop_types[] = |
| 746 | -{ |
| 747 | - { "STRING", 0, 0 }, |
| 748 | - { "text/plain", 0, 0}, |
| 749 | - { "text/uri-list", 0, 0} |
| 750 | -}; |
| 751 | -static const gint n_drop_types = G_N_ELEMENTS(drop_types); |
| 752 | - |
| 753 | -static void |
| 754 | -update_hints (WnckWindow *window, GtkWidget *button) |
| 755 | -{ |
| 756 | - GtkWidget *parent; |
| 757 | - gint x, y, x1, y1; |
| 758 | - |
| 759 | - /* Skip problems */ |
| 760 | - if (!WNCK_IS_WINDOW (window)) return; |
| 761 | - if (!GTK_IS_WIDGET (button)) return; |
| 762 | - |
| 763 | - /* Skip invisible windows */ |
| 764 | - if (!GTK_WIDGET_VISIBLE (button)) return; |
| 765 | - |
| 766 | - x = y = 0; |
| 767 | - |
| 768 | - /* Recursively compute the button's coordinates */ |
| 769 | - for (parent = button; parent; parent = parent->parent) |
| 770 | - { |
| 771 | - if (parent->parent) |
| 772 | - { |
| 773 | - x += parent->allocation.x; |
| 774 | - y += parent->allocation.y; |
| 775 | - } |
| 776 | - else |
| 777 | - { |
| 778 | - x1 = y1 = 0; |
| 779 | - if (GDK_IS_WINDOW (parent->window)) |
| 780 | - gdk_window_get_origin (parent->window, &x1, &y1); |
| 781 | - x += x1; y += y1; |
| 782 | - break; |
| 783 | - } |
| 784 | - } |
| 785 | - |
| 786 | - /* Set the minimize hint for the window */ |
| 787 | - wnck_window_set_icon_geometry (window, x, y, |
| 788 | - button->allocation.width, |
| 789 | - button->allocation.height); |
| 790 | -} |
| 791 | - |
| 792 | -static void |
| 793 | -set_minimize_hints (TaskList *list) |
| 794 | -{ |
| 795 | - TaskListPrivate *priv; |
| 796 | - |
| 797 | - g_return_if_fail (TASK_IS_LIST (list)); |
| 798 | - priv = list->priv; |
| 799 | - |
| 800 | - g_hash_table_foreach (priv->win_table, |
| 801 | - (GHFunc)update_hints, |
| 802 | - NULL); |
| 803 | - |
| 804 | -} |
| 805 | - |
| 806 | -/* |
| 807 | - * Show all windows code |
| 808 | - */ |
| 809 | -static gboolean |
| 810 | -ensure_list (TaskList *list) |
| 811 | -{ |
| 812 | - TaskListPrivate *priv = list->priv; |
| 813 | - WnckWorkspace *current; |
| 814 | - GList *children, *c; |
| 815 | - |
| 816 | - current = wnck_screen_get_active_workspace (priv->screen); |
| 817 | - |
| 818 | - if (!WNCK_IS_WORKSPACE (current)) |
| 819 | - return FALSE; |
| 820 | - |
| 821 | - children = gtk_container_get_children (GTK_CONTAINER (list)); |
| 822 | - for (c = children; c; c = c->next) |
| 823 | - { |
| 824 | - GtkWidget *widget = c->data; |
| 825 | - WnckWindow *window = g_object_get_data (G_OBJECT (widget), "WnckWindow"); |
| 826 | - |
| 827 | - if (priv->show_all_windows |
| 828 | - || (wnck_window_is_on_workspace (window, current) |
| 829 | - && wnck_window_is_in_viewport (window, current))) |
| 830 | - { |
| 831 | - if (!wnck_window_is_skip_tasklist (window)) |
| 832 | - gtk_widget_show (widget); |
| 833 | - } |
| 834 | - else |
| 835 | - { |
| 836 | - gtk_widget_hide (widget); |
| 837 | - } |
| 838 | - } |
| 839 | - g_list_free (children); |
| 840 | - |
| 841 | - /* Re-set minimize hints */ |
| 842 | - set_minimize_hints (list); |
| 843 | - |
| 844 | - return FALSE; |
| 845 | -} |
| 846 | - |
| 847 | static void |
| 848 | task_list_set_show_all_windows (TaskList *list, gboolean show_all_windows) |
| 849 | { |
| 850 | @@ -154,252 +52,16 @@ |
| 851 | |
| 852 | priv->show_all_windows = show_all_windows; |
| 853 | |
| 854 | - ensure_list (list); |
| 855 | - |
| 856 | g_debug ("Show all windows: %s", show_all_windows ? "true" : "false"); |
| 857 | } |
| 858 | |
| 859 | -/* Callback */ |
| 860 | -static gboolean |
| 861 | -on_leave_notify_event (GtkWidget *button, |
| 862 | - GdkEventCrossing *event, |
| 863 | - TaskList *list) |
| 864 | -{ |
| 865 | - g_return_val_if_fail (TASK_IS_LIST (list), FALSE); |
| 866 | - |
| 867 | - gtk_widget_queue_draw (GTK_WIDGET (list)); |
| 868 | - |
| 869 | - return FALSE; |
| 870 | -} |
| 871 | - |
| 872 | -static gboolean |
| 873 | -on_button_released (GtkWidget *button, |
| 874 | - GdkEventButton *event, |
| 875 | - WnckWindow *window) |
| 876 | -{ |
| 877 | - g_return_val_if_fail (WNCK_IS_WINDOW (window), FALSE); |
| 878 | - |
| 879 | - if (event->button == 1) |
| 880 | - { |
| 881 | - WnckWorkspace *space; |
| 882 | - |
| 883 | - if (wnck_window_is_active (window)) |
| 884 | - { |
| 885 | - wnck_window_minimize (window); |
| 886 | - } |
| 887 | - else |
| 888 | - { |
| 889 | - space = wnck_window_get_workspace (window); |
| 890 | - wnck_workspace_activate (space, event->time); |
| 891 | - wnck_window_activate (window, event->time); |
| 892 | - } |
| 893 | - |
| 894 | - return TRUE; |
| 895 | - } |
| 896 | - |
| 897 | - return FALSE; |
| 898 | -} |
| 899 | - |
| 900 | -static gboolean |
| 901 | -on_button_pressed (GtkWidget *button, |
| 902 | - GdkEventButton *event, |
| 903 | - WnckWindow *window) |
| 904 | -{ |
| 905 | - g_return_val_if_fail (WNCK_IS_WINDOW (window), FALSE); |
| 906 | - |
| 907 | - if (event->button == 3) |
| 908 | - { |
| 909 | - GtkWidget *menu = wnck_action_menu_new (window); |
| 910 | - gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, |
| 911 | - event->button, event->time); |
| 912 | - return TRUE; |
| 913 | - } |
| 914 | - |
| 915 | - return FALSE; |
| 916 | -} |
| 917 | - |
| 918 | -static gboolean |
| 919 | -on_query_tooltip (GtkWidget *button, |
| 920 | - gint x, gint y, |
| 921 | - gboolean keyboard_mode, |
| 922 | - GtkTooltip *tooltip, |
| 923 | - WnckWindow *window) |
| 924 | -{ |
| 925 | - g_return_val_if_fail (WNCK_IS_WINDOW (window), FALSE); |
| 926 | - |
| 927 | - gtk_tooltip_set_text (tooltip, wnck_window_get_name(window)); |
| 928 | - gtk_tooltip_set_icon (tooltip, wnck_window_get_icon (window)); |
| 929 | - |
| 930 | - return TRUE; |
| 931 | -} |
| 932 | - |
| 933 | -static gboolean |
| 934 | -activate_window (GtkWidget *button) |
| 935 | -{ |
| 936 | - gint active; |
| 937 | - |
| 938 | - g_return_val_if_fail (GTK_IS_WIDGET (button), FALSE); |
| 939 | - |
| 940 | - active = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button), "drag-true")); |
| 941 | - |
| 942 | - if (active) |
| 943 | - { |
| 944 | - WnckWindow *window; |
| 945 | - |
| 946 | - window = (WnckWindow*)g_object_get_data (G_OBJECT (button), "WnckWindow"); |
| 947 | - if (WNCK_IS_WINDOW (window)) |
| 948 | - wnck_window_activate (window, time (NULL)); |
| 949 | - } |
| 950 | - |
| 951 | - g_object_set_data (G_OBJECT (button), "drag-true", GINT_TO_POINTER (0)); |
| 952 | - |
| 953 | - return FALSE; |
| 954 | -} |
| 955 | - |
| 956 | -static void |
| 957 | -on_drag_leave (GtkWidget *button, |
| 958 | - GdkDragContext *context, |
| 959 | - guint time) |
| 960 | -{ |
| 961 | - g_object_set_data (G_OBJECT (button), "drag-true", GINT_TO_POINTER (0)); |
| 962 | -} |
| 963 | - |
| 964 | -static gboolean |
| 965 | -on_drag_motion (GtkWidget *button, |
| 966 | - GdkDragContext *context, |
| 967 | - gint x, |
| 968 | - gint y, |
| 969 | - guint t) |
| 970 | -{ |
| 971 | - gint active; |
| 972 | - |
| 973 | - active = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button), "drag-true")); |
| 974 | - |
| 975 | - if (!active) |
| 976 | - { |
| 977 | - g_object_set_data (G_OBJECT (button), "drag-true", GINT_TO_POINTER (1)); |
| 978 | - |
| 979 | - g_timeout_add (1000, (GSourceFunc)activate_window, button); |
| 980 | - } |
| 981 | - |
| 982 | - return FALSE; |
| 983 | -} |
| 984 | - |
| 985 | -static void |
| 986 | -on_icon_changed (WnckWindow *window, GtkButton *button) |
| 987 | -{ |
| 988 | - if (WNCK_IS_WINDOW (window) && GTK_IS_BUTTON (button)) |
| 989 | - { |
| 990 | - gtk_image_set_from_pixbuf (GTK_IMAGE (gtk_button_get_image (button)), |
| 991 | - wnck_window_get_mini_icon (window)); |
| 992 | - gtk_widget_queue_draw (GTK_WIDGET (button)); |
| 993 | - } |
| 994 | -} |
| 995 | - |
| 996 | -static void |
| 997 | -set_state (WnckWindow *window, GtkButton *button, gboolean *found) |
| 998 | -{ |
| 999 | - TaskListPrivate *priv = TASK_LIST (task_list_get_default ())->priv; |
| 1000 | - |
| 1001 | - /* Skip problems */ |
| 1002 | - if (!WNCK_IS_WINDOW (window)) |
| 1003 | - return; |
| 1004 | - if (!GTK_IS_WIDGET (button)) |
| 1005 | - return; |
| 1006 | - |
| 1007 | - /* Skip invisible windows */ |
| 1008 | - if (!GTK_WIDGET_VISIBLE (button)) |
| 1009 | - return; |
| 1010 | - |
| 1011 | - /* Skip windows that don't need attention */ |
| 1012 | - if (!wnck_window_or_transient_needs_attention (window)) |
| 1013 | - return; |
| 1014 | - |
| 1015 | - /* Blink the button */ |
| 1016 | - gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), |
| 1017 | - priv->counter & 1); |
| 1018 | - |
| 1019 | - /* Don't destroy the timeout */ |
| 1020 | - *found = TRUE; |
| 1021 | -} |
| 1022 | - |
| 1023 | -static gboolean |
| 1024 | -on_blink (TaskList *list) |
| 1025 | -{ |
| 1026 | - TaskListPrivate *priv; |
| 1027 | - gboolean found = FALSE; |
| 1028 | - |
| 1029 | - g_return_val_if_fail (TASK_IS_LIST (list), FALSE); |
| 1030 | - priv = list->priv; |
| 1031 | - |
| 1032 | - /* Increment the blink counter */ |
| 1033 | - priv->counter ++; |
| 1034 | - |
| 1035 | - g_hash_table_foreach (priv->win_table, |
| 1036 | - (GHFunc)set_state, |
| 1037 | - &found); |
| 1038 | - |
| 1039 | - /* Continue the periodic timeout if needed */ |
| 1040 | - if (!found) priv->timer = 0; |
| 1041 | - return found; |
| 1042 | -} |
| 1043 | - |
| 1044 | -static void |
| 1045 | -on_state_changed (WnckWindow *window, |
| 1046 | - WnckWindowState changed_mask, |
| 1047 | - WnckWindowState new_state, |
| 1048 | - TaskList *list) |
| 1049 | -{ |
| 1050 | - TaskListPrivate *priv; |
| 1051 | - GtkWidget *button; |
| 1052 | - WnckWorkspace *current; |
| 1053 | - |
| 1054 | - g_return_if_fail (WNCK_IS_WINDOW (window)); |
| 1055 | - g_return_if_fail (TASK_IS_LIST (list)); |
| 1056 | - priv = list->priv; |
| 1057 | - |
| 1058 | - /* Get the button */ |
| 1059 | - button = g_hash_table_lookup (priv->win_table, window); |
| 1060 | - g_return_if_fail (GTK_IS_WIDGET (button)); |
| 1061 | - |
| 1062 | - /* Get the workspace */ |
| 1063 | - current = wnck_screen_get_active_workspace (priv->screen); |
| 1064 | - |
| 1065 | - /* Check if the button should be hidden */ |
| 1066 | - if (wnck_window_is_skip_tasklist (window) |
| 1067 | - || (current |
| 1068 | - && !wnck_window_is_on_workspace (window, current) |
| 1069 | - && !priv->show_all_windows)) |
| 1070 | - gtk_widget_hide (button); |
| 1071 | - else |
| 1072 | - { |
| 1073 | - gtk_widget_show (button); |
| 1074 | - |
| 1075 | - /* If the window needs attention and there is no timer... */ |
| 1076 | - if (!priv->timer && |
| 1077 | - wnck_window_or_transient_needs_attention (window) ) |
| 1078 | - { |
| 1079 | - /* Start the timer */ |
| 1080 | - priv->timer = g_timeout_add (500, (GSourceFunc)on_blink, list); |
| 1081 | - priv->counter = 0; |
| 1082 | - } |
| 1083 | - } |
| 1084 | - |
| 1085 | - /* Update the button's state */ |
| 1086 | - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), |
| 1087 | - wnck_screen_get_active_window (priv->screen) == window); |
| 1088 | - |
| 1089 | - /* Re-set minimize hints */ |
| 1090 | - ensure_list (list); |
| 1091 | - set_minimize_hints (list); |
| 1092 | -} |
| 1093 | - |
| 1094 | -static void |
| 1095 | -on_workspace_changed (WnckWindow *window, TaskList *list) |
| 1096 | -{ |
| 1097 | - g_return_if_fail (TASK_IS_LIST (list)); |
| 1098 | - |
| 1099 | - ensure_list (list); |
| 1100 | +static void |
| 1101 | +on_task_item_closed (TaskItem *item, |
| 1102 | + TaskList *list) |
| 1103 | +{ |
| 1104 | + gtk_container_remove (GTK_CONTAINER (list), |
| 1105 | + GTK_WIDGET (item)); |
| 1106 | + gtk_widget_destroy (GTK_WIDGET (item)); |
| 1107 | } |
| 1108 | |
| 1109 | static void |
| 1110 | @@ -409,7 +71,6 @@ |
| 1111 | { |
| 1112 | TaskListPrivate *priv; |
| 1113 | WnckWindowType type; |
| 1114 | - GtkWidget *button; |
| 1115 | |
| 1116 | g_return_if_fail (TASK_IS_LIST (list)); |
| 1117 | priv = list->priv; |
| 1118 | @@ -422,123 +83,21 @@ |
| 1119 | || type == WNCK_WINDOW_MENU) |
| 1120 | return; |
| 1121 | |
| 1122 | - button = g_object_new (GTK_TYPE_TOGGLE_BUTTON, |
| 1123 | - "has-tooltip", TRUE, |
| 1124 | - "image", gtk_image_new_from_pixbuf ( |
| 1125 | - wnck_window_get_mini_icon (window)), |
| 1126 | - "name", "tasklist-button2", |
| 1127 | - "relief", GTK_RELIEF_NONE, |
| 1128 | - NULL); |
| 1129 | - /* D&D */ |
| 1130 | - gtk_widget_add_events (GTK_WIDGET (button),GDK_ALL_EVENTS_MASK); |
| 1131 | - gtk_drag_dest_set (GTK_WIDGET (button), |
| 1132 | - GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP, |
| 1133 | - drop_types, n_drop_types, |
| 1134 | - GDK_ACTION_COPY); |
| 1135 | - gtk_drag_dest_add_uri_targets (GTK_WIDGET (button)); |
| 1136 | - gtk_drag_dest_add_text_targets (GTK_WIDGET (button)); |
| 1137 | - g_signal_connect (button, "drag-motion", |
| 1138 | - G_CALLBACK (on_drag_motion), NULL); |
| 1139 | - g_signal_connect (button, "drag-leave", |
| 1140 | - G_CALLBACK (on_drag_leave), NULL); |
| 1141 | - |
| 1142 | - gtk_box_pack_start (GTK_BOX (list), button, FALSE, FALSE, 0); |
| 1143 | - |
| 1144 | - g_signal_connect (button, "button-release-event", |
| 1145 | - G_CALLBACK (on_button_released), window); |
| 1146 | - g_signal_connect (button, "button-press-event", |
| 1147 | - G_CALLBACK (on_button_pressed), window); |
| 1148 | - g_signal_connect (button, "leave-notify-event", |
| 1149 | - G_CALLBACK (on_leave_notify_event), list); |
| 1150 | - g_signal_connect (button, "query-tooltip", |
| 1151 | - G_CALLBACK (on_query_tooltip), window); |
| 1152 | - g_signal_connect (window, "icon-changed", |
| 1153 | - G_CALLBACK (on_icon_changed), button); |
| 1154 | - g_signal_connect (window, "state-changed", |
| 1155 | - G_CALLBACK (on_state_changed), list); |
| 1156 | - g_signal_connect (window, "workspace-changed", |
| 1157 | - G_CALLBACK (on_workspace_changed), list); |
| 1158 | - |
| 1159 | - g_hash_table_insert (priv->win_table, window, button); |
| 1160 | - g_object_set_data (G_OBJECT (button), "WnckWindow", window); |
| 1161 | - |
| 1162 | - /* Do an initial state change to avoid code duplication here */ |
| 1163 | - on_state_changed (window, 0xFFFFFFFF, wnck_window_get_state (window), list); |
| 1164 | - |
| 1165 | - /* Show the window if it's button is visible (why??) */ |
| 1166 | + /* Show the window if it's button is visible (why??) |
| 1167 | + BECAUSE IT'S DUMB, that explains the urgency behavior.... |
| 1168 | if (GTK_WIDGET_VISIBLE (button)) |
| 1169 | - wnck_window_activate (window, GDK_CURRENT_TIME); |
| 1170 | -} |
| 1171 | - |
| 1172 | -static void |
| 1173 | -on_window_closed (WnckScreen *screen, |
| 1174 | - WnckWindow *window, |
| 1175 | - TaskList *list) |
| 1176 | -{ |
| 1177 | - TaskListPrivate *priv; |
| 1178 | - GtkWidget *button; |
| 1179 | - |
| 1180 | - g_return_if_fail (TASK_IS_LIST (list)); |
| 1181 | - priv = list->priv; |
| 1182 | - |
| 1183 | - button = g_hash_table_lookup (priv->win_table, window); |
| 1184 | - |
| 1185 | - if (GTK_IS_WIDGET (button)) |
| 1186 | - gtk_widget_destroy (button); |
| 1187 | - |
| 1188 | - g_hash_table_remove (priv->win_table, window); |
| 1189 | - |
| 1190 | - /* Set minimize hints */ |
| 1191 | - set_minimize_hints (list); |
| 1192 | -} |
| 1193 | - |
| 1194 | -static void |
| 1195 | -on_active_window_changed (WnckScreen *screen, |
| 1196 | - WnckWindow *old_window, |
| 1197 | - TaskList *list) |
| 1198 | -{ |
| 1199 | - TaskListPrivate *priv; |
| 1200 | - WnckWindow *act_window; |
| 1201 | - GtkWidget *old_button; |
| 1202 | - GtkWidget *act_button; |
| 1203 | - |
| 1204 | - g_return_if_fail (TASK_IS_LIST (list)); |
| 1205 | - priv = list->priv; |
| 1206 | - |
| 1207 | - old_button = g_hash_table_lookup (priv->win_table, old_window); |
| 1208 | - if (GTK_IS_WIDGET (old_button)) |
| 1209 | - { |
| 1210 | - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (old_button), FALSE); |
| 1211 | - } |
| 1212 | - |
| 1213 | - act_window = wnck_screen_get_active_window (priv->screen); |
| 1214 | - act_button = g_hash_table_lookup (priv->win_table, act_window); |
| 1215 | - if (GTK_IS_WIDGET (act_button)) |
| 1216 | - { |
| 1217 | - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (act_button), TRUE); |
| 1218 | - } |
| 1219 | - |
| 1220 | - ensure_list (list); |
| 1221 | -} |
| 1222 | - |
| 1223 | -static void |
| 1224 | -on_active_workspace_changed (WnckScreen *screen, |
| 1225 | - WnckWorkspace *old_workspace, |
| 1226 | - TaskList *list) |
| 1227 | -{ |
| 1228 | - g_return_if_fail (TASK_IS_LIST (list)); |
| 1229 | - |
| 1230 | - ensure_list (list); |
| 1231 | -} |
| 1232 | - |
| 1233 | -static void |
| 1234 | -on_active_viewport_changed (WnckScreen *screen, |
| 1235 | - TaskList *list) |
| 1236 | -{ |
| 1237 | - g_return_if_fail (TASK_IS_LIST (list)); |
| 1238 | - |
| 1239 | - ensure_list (list); |
| 1240 | -} |
| 1241 | + wnck_window_activate (window, GDK_CURRENT_TIME); */ |
| 1242 | + |
| 1243 | + GtkWidget *item = task_item_new (window); |
| 1244 | + |
| 1245 | + if (item) |
| 1246 | + { |
| 1247 | + gtk_box_pack_start (GTK_BOX (list), item, FALSE, FALSE, 0); |
| 1248 | + g_signal_connect (TASK_ITEM (item), "task-item-closed", |
| 1249 | + G_CALLBACK (on_task_item_closed), list); |
| 1250 | + } |
| 1251 | +} |
| 1252 | + |
| 1253 | /* GObject stuff */ |
| 1254 | static void |
| 1255 | task_list_finalize (GObject *object) |
| 1256 | @@ -635,14 +194,6 @@ |
| 1257 | |
| 1258 | g_signal_connect (priv->screen, "window-opened", |
| 1259 | G_CALLBACK (on_window_opened), list); |
| 1260 | - g_signal_connect (priv->screen, "window-closed", |
| 1261 | - G_CALLBACK (on_window_closed), list); |
| 1262 | - g_signal_connect (priv->screen, "active-workspace-changed", |
| 1263 | - G_CALLBACK (on_active_workspace_changed), list); |
| 1264 | - g_signal_connect (priv->screen, "viewports-changed", |
| 1265 | - G_CALLBACK (on_active_viewport_changed), list); |
| 1266 | - g_signal_connect (priv->screen, "active-window-changed", |
| 1267 | - G_CALLBACK (on_active_window_changed), list); |
| 1268 | } |
| 1269 | |
| 1270 | GtkWidget * |
| 1271 | @@ -656,8 +207,6 @@ |
| 1272 | "spacing", 2, |
| 1273 | NULL); |
| 1274 | |
| 1275 | - g_idle_add ((GSourceFunc)ensure_list, list); |
| 1276 | - |
| 1277 | return list; |
| 1278 | } |
| 1279 | |
| 1280 | @@ -675,23 +224,28 @@ |
| 1281 | gboolean |
| 1282 | task_list_get_desktop_visible (TaskList *list) |
| 1283 | { |
| 1284 | - GList *children, *c; |
| 1285 | + GList *windows, *w; |
| 1286 | gboolean all_minimised = TRUE; |
| 1287 | |
| 1288 | g_return_val_if_fail (TASK_IS_LIST (list), TRUE); |
| 1289 | |
| 1290 | - children = gtk_container_get_children (GTK_CONTAINER (list)); |
| 1291 | - for (c = children; c; c = c->next) |
| 1292 | + windows = wnck_screen_get_windows (list->priv->screen); |
| 1293 | + for (w = windows; w; w = w->next) |
| 1294 | { |
| 1295 | WnckWindow *window; |
| 1296 | |
| 1297 | - window = g_object_get_data (G_OBJECT (c->data), "WnckWindow"); |
| 1298 | + window = w->data; |
| 1299 | |
| 1300 | if (WNCK_IS_WINDOW (window) && !wnck_window_is_minimized (window)) |
| 1301 | all_minimised = FALSE; |
| 1302 | } |
| 1303 | - g_list_free (children); |
| 1304 | |
| 1305 | return all_minimised; |
| 1306 | } |
| 1307 | |
| 1308 | +gboolean |
| 1309 | +task_list_get_show_all_windows (TaskList *list) |
| 1310 | +{ |
| 1311 | + return list->priv->show_all_windows; |
| 1312 | +} |
| 1313 | + |
| 1314 | |
| 1315 | === modified file 'src/task-list.h' |
| 1316 | --- src/task-list.h 2009-03-04 16:14:38 +0000 |
| 1317 | +++ src/task-list.h 2009-08-21 07:06:29 +0000 |
| 1318 | @@ -64,5 +64,7 @@ |
| 1319 | |
| 1320 | gboolean task_list_get_desktop_visible (TaskList *list); |
| 1321 | |
| 1322 | +gboolean task_list_get_show_all_windows (TaskList *list); |
| 1323 | + |
| 1324 | #endif /* _TASK_LIST_H_ */ |
| 1325 | |
| 1326 | |
| 1327 | === modified file 'src/task-title.c' |
| 1328 | --- src/task-title.c 2009-05-04 19:57:27 +0000 |
| 1329 | +++ src/task-title.c 2009-08-21 09:12:47 +0000 |
| 1330 | @@ -43,13 +43,13 @@ |
| 1331 | WnckWindow *window; |
| 1332 | GtkWidget *align; |
| 1333 | GtkWidget *box; |
| 1334 | - GtkWidget *image; |
| 1335 | GtkWidget *label; |
| 1336 | GtkWidget *button; |
| 1337 | GtkWidget *button_image; |
| 1338 | GdkPixbuf *quit_icon; |
| 1339 | |
| 1340 | gboolean show_home_title; |
| 1341 | + gboolean mouse_in_close_button; |
| 1342 | }; |
| 1343 | |
| 1344 | static void disconnect_window (TaskTitle *title); |
| 1345 | @@ -87,6 +87,60 @@ |
| 1346 | return TRUE; |
| 1347 | } |
| 1348 | |
| 1349 | +static gboolean |
| 1350 | +on_enter_notify (GtkWidget *widget, |
| 1351 | + GdkEventCrossing *event, |
| 1352 | + TaskTitle *title) |
| 1353 | +{ |
| 1354 | + g_return_val_if_fail (TASK_IS_TITLE (title), FALSE); |
| 1355 | + |
| 1356 | + title->priv->mouse_in_close_button = TRUE; |
| 1357 | + gtk_widget_queue_draw (widget); |
| 1358 | + |
| 1359 | + return FALSE; |
| 1360 | +} |
| 1361 | + |
| 1362 | +static gboolean |
| 1363 | +on_leave_notify (GtkWidget *widget, |
| 1364 | + GdkEventCrossing *event, |
| 1365 | + TaskTitle *title) |
| 1366 | +{ |
| 1367 | + g_return_val_if_fail (TASK_IS_TITLE (title), FALSE); |
| 1368 | + |
| 1369 | + title->priv->mouse_in_close_button = FALSE; |
| 1370 | + gtk_widget_queue_draw (widget); |
| 1371 | + |
| 1372 | + return FALSE; |
| 1373 | +} |
| 1374 | + |
| 1375 | +static gboolean |
| 1376 | +on_button_expose (GtkWidget *widget, |
| 1377 | + GdkEventExpose *event, |
| 1378 | + TaskTitle *title) |
| 1379 | +{ |
| 1380 | + g_return_val_if_fail (TASK_IS_TITLE (title), FALSE); |
| 1381 | + |
| 1382 | + TaskTitlePrivate *priv; |
| 1383 | + priv = title->priv; |
| 1384 | + |
| 1385 | + if (priv->mouse_in_close_button) |
| 1386 | + { |
| 1387 | + GtkStyle *style = gtk_widget_get_style (widget); |
| 1388 | + gtk_paint_box (style, |
| 1389 | + event->window, |
| 1390 | + GTK_STATE_PRELIGHT, |
| 1391 | + GTK_SHADOW_NONE, |
| 1392 | + NULL, |
| 1393 | + NULL, |
| 1394 | + NULL, |
| 1395 | + event->area.x, |
| 1396 | + event->area.y + 2, |
| 1397 | + event->area.width, |
| 1398 | + event->area.height - 4); |
| 1399 | + } |
| 1400 | + return FALSE; |
| 1401 | +} |
| 1402 | + |
| 1403 | static void |
| 1404 | on_name_changed (WnckWindow *window, TaskTitle *title) |
| 1405 | { |
| 1406 | @@ -119,8 +173,6 @@ |
| 1407 | if (priv->window != window) |
| 1408 | return; |
| 1409 | |
| 1410 | - gtk_image_set_from_pixbuf (GTK_IMAGE (title->priv->image), |
| 1411 | - wnck_window_get_mini_icon (window)); |
| 1412 | gtk_widget_queue_draw (GTK_WIDGET (title)); |
| 1413 | } |
| 1414 | |
| 1415 | @@ -196,8 +248,6 @@ |
| 1416 | { |
| 1417 | if (priv->show_home_title) |
| 1418 | { |
| 1419 | - gtk_image_set_from_stock (GTK_IMAGE (priv->image), |
| 1420 | - GTK_STOCK_HOME, GTK_ICON_SIZE_MENU); |
| 1421 | gtk_label_set_text (GTK_LABEL (priv->label), _("Home")); |
| 1422 | gtk_image_set_from_pixbuf (GTK_IMAGE (priv->button_image), |
| 1423 | priv->quit_icon); |
| 1424 | @@ -217,8 +267,6 @@ |
| 1425 | } |
| 1426 | else |
| 1427 | { |
| 1428 | - gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image), |
| 1429 | - wnck_window_get_mini_icon (act_window)); |
| 1430 | gtk_label_set_text (GTK_LABEL (priv->label), |
| 1431 | wnck_window_get_name (act_window)); |
| 1432 | gtk_image_set_from_stock (GTK_IMAGE (priv->button_image), |
| 1433 | @@ -250,8 +298,6 @@ |
| 1434 | if (task_list_get_desktop_visible (TASK_LIST (task_list_get_default ())) |
| 1435 | && priv->show_home_title) |
| 1436 | { |
| 1437 | - gtk_image_set_from_stock (GTK_IMAGE (priv->image), |
| 1438 | - GTK_STOCK_HOME, GTK_ICON_SIZE_MENU); |
| 1439 | gtk_label_set_text (GTK_LABEL (priv->label), _("Home")); |
| 1440 | gtk_image_set_from_pixbuf (GTK_IMAGE (priv->button_image), |
| 1441 | priv->quit_icon); |
| 1442 | @@ -380,13 +426,15 @@ |
| 1443 | gtk_widget_set_no_show_all (priv->box, TRUE); |
| 1444 | gtk_widget_show (priv->box); |
| 1445 | |
| 1446 | - priv->image = gtk_image_new_from_stock (GTK_STOCK_HOME, GTK_ICON_SIZE_MENU); |
| 1447 | - gtk_box_pack_start (GTK_BOX (priv->box), priv->image, FALSE, FALSE, 0); |
| 1448 | - gtk_widget_show (priv->image); |
| 1449 | - |
| 1450 | priv->label = gtk_label_new (_("Home")); |
| 1451 | gtk_label_set_ellipsize (GTK_LABEL (priv->label), PANGO_ELLIPSIZE_END); |
| 1452 | gtk_misc_set_alignment (GTK_MISC (priv->label), 0.0, 0.5); |
| 1453 | + |
| 1454 | + PangoAttrList *attr_list = pango_attr_list_new (); |
| 1455 | + PangoAttribute *attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD); |
| 1456 | + pango_attr_list_insert (attr_list, attr); |
| 1457 | + gtk_label_set_attributes (GTK_LABEL (priv->label), attr_list); |
| 1458 | + |
| 1459 | gtk_box_pack_start (GTK_BOX (priv->box), priv->label, TRUE, TRUE, 0); |
| 1460 | gtk_widget_show (priv->label); |
| 1461 | |
| 1462 | @@ -396,8 +444,15 @@ |
| 1463 | NULL); |
| 1464 | gtk_box_pack_start (GTK_BOX (priv->box), priv->button, FALSE, FALSE, 0); |
| 1465 | gtk_widget_show (priv->button); |
| 1466 | + |
| 1467 | g_signal_connect (priv->button, "button-release-event", |
| 1468 | G_CALLBACK (on_close_clicked), title); |
| 1469 | + g_signal_connect (priv->button, "enter-notify-event", |
| 1470 | + G_CALLBACK (on_enter_notify), title); |
| 1471 | + g_signal_connect (priv->button, "leave-notify-event", |
| 1472 | + G_CALLBACK (on_leave_notify), title); |
| 1473 | + g_signal_connect (priv->button, "expose-event", |
| 1474 | + G_CALLBACK (on_button_expose), title); |
| 1475 | |
| 1476 | /* Load the quit icon. We have to do this in such a god-forsaken way |
| 1477 | because of http://bugzilla.gnome.org/show_bug.cgi?id=581359 and the |
- Window items are now their own class and self managing
- Window item icons are full size of the panel (contain small click detection bug)
- Active window item is fully opaque, inactive items are slightly transparent
- Title bar has lost extra icon
- Title bar contains bold text
- Title bar now properly prelights the close button, this however will need to be themed properly in the gtkrc file
- Window items that set the urgent status now slowly (around 1 second) fade in and out to indicate this, rather than sudden blinks. Very passive.