00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <config.h>
00027 #include "workspace.h"
00028 #include "errors.h"
00029 #include "prefs.h"
00030 #include <X11/Xatom.h>
00031 #include <string.h>
00032
00033 void meta_workspace_queue_calc_showing (MetaWorkspace *workspace);
00034 static void set_active_space_hint (MetaScreen *screen);
00035 static void focus_ancestor_or_mru_window (MetaWorkspace *workspace,
00036 MetaWindow *not_this_one,
00037 guint32 timestamp);
00038
00039 static void
00040 maybe_add_to_list (MetaScreen *screen, MetaWindow *window, gpointer data)
00041 {
00042 GList **mru_list = data;
00043
00044 if (window->on_all_workspaces)
00045 *mru_list = g_list_prepend (*mru_list, window);
00046 }
00047
00048 MetaWorkspace*
00049 meta_workspace_new (MetaScreen *screen)
00050 {
00051 MetaWorkspace *workspace;
00052
00053 workspace = g_new (MetaWorkspace, 1);
00054
00055 workspace->screen = screen;
00056 workspace->screen->workspaces =
00057 g_list_append (workspace->screen->workspaces, workspace);
00058 workspace->windows = NULL;
00059 workspace->mru_list = NULL;
00060 meta_screen_foreach_window (screen, maybe_add_to_list, &workspace->mru_list);
00061
00062 workspace->work_areas_invalid = TRUE;
00063 workspace->work_area_xinerama = NULL;
00064 workspace->work_area_screen.x = 0;
00065 workspace->work_area_screen.y = 0;
00066 workspace->work_area_screen.width = 0;
00067 workspace->work_area_screen.height = 0;
00068
00069 workspace->screen_region = NULL;
00070 workspace->xinerama_region = NULL;
00071 workspace->screen_edges = NULL;
00072 workspace->xinerama_edges = NULL;
00073 workspace->list_containing_self = g_list_prepend (NULL, workspace);
00074
00075 workspace->all_struts = NULL;
00076
00077 workspace->showing_desktop = FALSE;
00078
00079 return workspace;
00080 }
00081
00082 void
00083 meta_workspace_free (MetaWorkspace *workspace)
00084 {
00085 GList *tmp;
00086 MetaScreen *screen;
00087 int i;
00088
00089 g_return_if_fail (workspace != workspace->screen->active_workspace);
00090
00091
00092
00093
00094
00095 tmp = workspace->windows;
00096 while (tmp != NULL)
00097 {
00098 GList *next;
00099 MetaWindow *window = tmp->data;
00100 next = tmp->next;
00101
00102
00103 meta_workspace_remove_window (workspace, window);
00104 g_assert (window->workspace != NULL);
00105
00106 tmp = next;
00107 }
00108
00109 g_assert (workspace->windows == NULL);
00110
00111 screen = workspace->screen;
00112
00113 workspace->screen->workspaces =
00114 g_list_remove (workspace->screen->workspaces, workspace);
00115
00116 g_free (workspace->work_area_xinerama);
00117
00118 g_list_free (workspace->mru_list);
00119 g_list_free (workspace->list_containing_self);
00120
00121
00122
00123
00124
00125
00126
00127
00128 if (!workspace->work_areas_invalid)
00129 {
00130 g_slist_free (workspace->all_struts);
00131 for (i = 0; i < screen->n_xinerama_infos; i++)
00132 meta_rectangle_free_list_and_elements (workspace->xinerama_region[i]);
00133 g_free (workspace->xinerama_region);
00134 meta_rectangle_free_list_and_elements (workspace->screen_region);
00135 meta_rectangle_free_list_and_elements (workspace->screen_edges);
00136 meta_rectangle_free_list_and_elements (workspace->xinerama_edges);
00137 }
00138
00139 g_free (workspace);
00140
00141
00142
00143
00144 }
00145
00146 void
00147 meta_workspace_add_window (MetaWorkspace *workspace,
00148 MetaWindow *window)
00149 {
00150 g_return_if_fail (window->workspace == NULL);
00151
00152
00153
00154
00155 if (window->on_all_workspaces)
00156 {
00157 if (window->workspace == NULL)
00158 {
00159 GList* tmp = window->screen->workspaces;
00160 while (tmp)
00161 {
00162 MetaWorkspace* work = (MetaWorkspace*) tmp->data;
00163 if (!g_list_find (work->mru_list, window))
00164 work->mru_list = g_list_prepend (work->mru_list, window);
00165
00166 tmp = tmp->next;
00167 }
00168 }
00169 }
00170 else
00171 {
00172 g_assert (g_list_find (workspace->mru_list, window) == NULL);
00173 workspace->mru_list = g_list_prepend (workspace->mru_list, window);
00174 }
00175
00176 workspace->windows = g_list_prepend (workspace->windows, window);
00177 window->workspace = workspace;
00178
00179 meta_window_set_current_workspace_hint (window);
00180
00181 if (window->struts)
00182 {
00183 meta_topic (META_DEBUG_WORKAREA,
00184 "Invalidating work area of workspace %d since we're adding window %s to it\n",
00185 meta_workspace_index (workspace), window->desc);
00186 meta_workspace_invalidate_work_area (workspace);
00187 }
00188
00189
00190
00191
00192 meta_window_queue (window, META_QUEUE_CALC_SHOWING|META_QUEUE_MOVE_RESIZE);
00193 }
00194
00195 void
00196 meta_workspace_remove_window (MetaWorkspace *workspace,
00197 MetaWindow *window)
00198 {
00199 g_return_if_fail (window->workspace == workspace);
00200
00201 workspace->windows = g_list_remove (workspace->windows, window);
00202 window->workspace = NULL;
00203
00204
00205
00206
00207
00208 if (window->on_all_workspaces)
00209 {
00210 GList* tmp = window->screen->workspaces;
00211 while (tmp)
00212 {
00213 MetaWorkspace* work = (MetaWorkspace*) tmp->data;
00214 work->mru_list = g_list_remove (work->mru_list, window);
00215
00216 tmp = tmp->next;
00217 }
00218 }
00219 else
00220 {
00221 workspace->mru_list = g_list_remove (workspace->mru_list, window);
00222 g_assert (g_list_find (workspace->mru_list, window) == NULL);
00223 }
00224
00225 meta_window_set_current_workspace_hint (window);
00226
00227 if (window->struts)
00228 {
00229 meta_topic (META_DEBUG_WORKAREA,
00230 "Invalidating work area of workspace %d since we're removing window %s from it\n",
00231 meta_workspace_index (workspace), window->desc);
00232 meta_workspace_invalidate_work_area (workspace);
00233 }
00234
00235
00236
00237
00238 meta_window_queue (window, META_QUEUE_CALC_SHOWING|META_QUEUE_MOVE_RESIZE);
00239 }
00240
00241 void
00242 meta_workspace_relocate_windows (MetaWorkspace *workspace,
00243 MetaWorkspace *new_home)
00244 {
00245 GList *tmp;
00246 GList *copy;
00247
00248 g_return_if_fail (workspace != new_home);
00249
00250
00251 copy = g_list_copy (workspace->windows);
00252
00253 tmp = copy;
00254 while (tmp != NULL)
00255 {
00256 MetaWindow *window = tmp->data;
00257
00258 meta_workspace_remove_window (workspace, window);
00259 meta_workspace_add_window (new_home, window);
00260
00261 tmp = tmp->next;
00262 }
00263
00264 g_list_free (copy);
00265
00266 g_assert (workspace->windows == NULL);
00267 }
00268
00269 void
00270 meta_workspace_queue_calc_showing (MetaWorkspace *workspace)
00271 {
00272 GList *tmp;
00273
00274 tmp = workspace->windows;
00275 while (tmp != NULL)
00276 {
00277 meta_window_queue (tmp->data, META_QUEUE_CALC_SHOWING);
00278
00279 tmp = tmp->next;
00280 }
00281 }
00282
00283 void
00284 meta_workspace_activate_with_focus (MetaWorkspace *workspace,
00285 MetaWindow *focus_this,
00286 guint32 timestamp)
00287 {
00288 MetaWorkspace *old;
00289 MetaWindow *move_window;
00290
00291 meta_verbose ("Activating workspace %d\n",
00292 meta_workspace_index (workspace));
00293
00294 if (workspace->screen->active_workspace == workspace)
00295 return;
00296
00297
00298 old = workspace->screen->active_workspace;
00299
00300 workspace->screen->active_workspace = workspace;
00301
00302 set_active_space_hint (workspace->screen);
00303
00304
00305
00306
00307
00308 if (old && (old->showing_desktop ^ workspace->showing_desktop))
00309 meta_screen_update_showing_desktop_hint (workspace->screen);
00310
00311 if (old == NULL)
00312 return;
00313
00314 move_window = NULL;
00315 if (workspace->screen->display->grab_op == META_GRAB_OP_MOVING ||
00316 workspace->screen->display->grab_op == META_GRAB_OP_KEYBOARD_MOVING)
00317 move_window = workspace->screen->display->grab_window;
00318
00319 if (move_window != NULL)
00320 {
00321 if (move_window->on_all_workspaces)
00322 move_window = NULL;
00323
00324
00325
00326
00327
00328
00329
00330
00331 if (move_window && (move_window->workspace != workspace))
00332 {
00333 meta_workspace_remove_window (old, move_window);
00334 meta_workspace_add_window (workspace, move_window);
00335 }
00336 }
00337
00338 meta_workspace_queue_calc_showing (old);
00339 meta_workspace_queue_calc_showing (workspace);
00340
00341
00342 if (move_window)
00343
00344 meta_window_change_workspace (move_window, workspace);
00345
00346 if (focus_this)
00347 {
00348 meta_window_focus (focus_this, timestamp);
00349 meta_window_raise (focus_this);
00350 }
00351 else if (move_window)
00352 {
00353 meta_window_raise (move_window);
00354 }
00355 else
00356 {
00357 meta_topic (META_DEBUG_FOCUS, "Focusing default window on new workspace\n");
00358 meta_workspace_focus_default_window (workspace, NULL, timestamp);
00359 }
00360 }
00361
00362 void
00363 meta_workspace_activate (MetaWorkspace *workspace,
00364 guint32 timestamp)
00365 {
00366 meta_workspace_activate_with_focus (workspace, NULL, timestamp);
00367 }
00368
00369 int
00370 meta_workspace_index (MetaWorkspace *workspace)
00371 {
00372 int ret;
00373
00374 ret = g_list_index (workspace->screen->workspaces, workspace);
00375
00376 if (ret < 0)
00377 meta_bug ("Workspace does not exist to index!\n");
00378
00379 return ret;
00380 }
00381
00382
00383
00384
00385 GList*
00386 meta_workspace_list_windows (MetaWorkspace *workspace)
00387 {
00388 GSList *display_windows;
00389 GSList *tmp;
00390 GList *workspace_windows;
00391
00392 display_windows = meta_display_list_windows (workspace->screen->display);
00393
00394 workspace_windows = NULL;
00395 tmp = display_windows;
00396 while (tmp != NULL)
00397 {
00398 MetaWindow *window = tmp->data;
00399
00400 if (meta_window_located_on_workspace (window, workspace))
00401 workspace_windows = g_list_prepend (workspace_windows,
00402 window);
00403
00404 tmp = tmp->next;
00405 }
00406
00407 g_slist_free (display_windows);
00408
00409 return workspace_windows;
00410 }
00411
00412 static void
00413 set_active_space_hint (MetaScreen *screen)
00414 {
00415 unsigned long data[1];
00416
00417
00418
00419
00420
00421
00422
00423 if (screen->closing > 0)
00424 return;
00425
00426 data[0] = meta_workspace_index (screen->active_workspace);
00427
00428 meta_verbose ("Setting _NET_CURRENT_DESKTOP to %lu\n", data[0]);
00429
00430 meta_error_trap_push (screen->display);
00431 XChangeProperty (screen->display->xdisplay, screen->xroot,
00432 screen->display->atom__NET_CURRENT_DESKTOP,
00433 XA_CARDINAL,
00434 32, PropModeReplace, (guchar*) data, 1);
00435 meta_error_trap_pop (screen->display, FALSE);
00436 }
00437
00438 void
00439 meta_workspace_invalidate_work_area (MetaWorkspace *workspace)
00440 {
00441 GList *tmp;
00442 GList *windows;
00443 int i;
00444
00445 if (workspace->work_areas_invalid)
00446 {
00447 meta_topic (META_DEBUG_WORKAREA,
00448 "Work area for workspace %d is already invalid\n",
00449 meta_workspace_index (workspace));
00450 return;
00451 }
00452
00453 meta_topic (META_DEBUG_WORKAREA,
00454 "Invalidating work area for workspace %d\n",
00455 meta_workspace_index (workspace));
00456
00457 g_free (workspace->work_area_xinerama);
00458 workspace->work_area_xinerama = NULL;
00459
00460 g_slist_free (workspace->all_struts);
00461 workspace->all_struts = NULL;
00462
00463 for (i = 0; i < workspace->screen->n_xinerama_infos; i++)
00464 meta_rectangle_free_list_and_elements (workspace->xinerama_region[i]);
00465 g_free (workspace->xinerama_region);
00466 meta_rectangle_free_list_and_elements (workspace->screen_region);
00467 meta_rectangle_free_list_and_elements (workspace->screen_edges);
00468 meta_rectangle_free_list_and_elements (workspace->xinerama_edges);
00469 workspace->xinerama_region = NULL;
00470 workspace->screen_region = NULL;
00471 workspace->screen_edges = NULL;
00472 workspace->xinerama_edges = NULL;
00473
00474 workspace->work_areas_invalid = TRUE;
00475
00476
00477 windows = meta_workspace_list_windows (workspace);
00478 tmp = windows;
00479 while (tmp != NULL)
00480 {
00481 MetaWindow *w = tmp->data;
00482
00483 meta_window_queue (w, META_QUEUE_MOVE_RESIZE);
00484
00485 tmp = tmp->next;
00486 }
00487
00488 g_list_free (windows);
00489
00490 meta_screen_queue_workarea_recalc (workspace->screen);
00491 }
00492
00493 static void
00494 ensure_work_areas_validated (MetaWorkspace *workspace)
00495 {
00496 GList *windows;
00497 GList *tmp;
00498 MetaRectangle work_area;
00499 int i;
00500
00501 if (!workspace->work_areas_invalid)
00502 return;
00503
00504 g_assert (workspace->all_struts == NULL);
00505 g_assert (workspace->xinerama_region == NULL);
00506 g_assert (workspace->screen_region == NULL);
00507 g_assert (workspace->screen_edges == NULL);
00508 g_assert (workspace->xinerama_edges == NULL);
00509
00510
00511 windows = meta_workspace_list_windows (workspace);
00512 for (tmp = windows; tmp != NULL; tmp = tmp->next)
00513 {
00514 MetaWindow *win = tmp->data;
00515 GSList *s_iter;
00516
00517 for (s_iter = win->struts; s_iter != NULL; s_iter = s_iter->next) {
00518 MetaStrut *cpy = g_new (MetaStrut, 1);
00519 *cpy = *((MetaStrut *)s_iter->data);
00520 workspace->all_struts = g_slist_prepend (workspace->all_struts,
00521 cpy);
00522 }
00523 }
00524 g_list_free (windows);
00525
00526
00527
00528
00529 g_assert (workspace->xinerama_region == NULL);
00530 g_assert (workspace->screen_region == NULL);
00531
00532 workspace->xinerama_region = g_new (GList*,
00533 workspace->screen->n_xinerama_infos);
00534 for (i = 0; i < workspace->screen->n_xinerama_infos; i++)
00535 {
00536 workspace->xinerama_region[i] =
00537 meta_rectangle_get_minimal_spanning_set_for_region (
00538 &workspace->screen->xinerama_infos[i].rect,
00539 workspace->all_struts);
00540 }
00541 workspace->screen_region =
00542 meta_rectangle_get_minimal_spanning_set_for_region (
00543 &workspace->screen->rect,
00544 workspace->all_struts);
00545
00546
00547
00548
00549 work_area = workspace->screen->rect;
00550 if (workspace->screen_region == NULL)
00551 work_area = meta_rect (0, 0, -1, -1);
00552 else
00553 meta_rectangle_clip_to_region (workspace->screen_region,
00554 FIXED_DIRECTION_NONE,
00555 &work_area);
00556
00557
00558 #define MIN_SANE_AREA 100
00559 if (work_area.width < MIN_SANE_AREA)
00560 {
00561 meta_warning ("struts occupy an unusually large percentage of the screen; "
00562 "available remaining width = %d < %d",
00563 work_area.width, MIN_SANE_AREA);
00564 if (work_area.width < 1)
00565 {
00566 work_area.x = (workspace->screen->rect.width - MIN_SANE_AREA)/2;
00567 work_area.width = MIN_SANE_AREA;
00568 }
00569 else
00570 {
00571 int amount = (MIN_SANE_AREA - work_area.width)/2;
00572 work_area.x -= amount;
00573 work_area.width += 2*amount;
00574 }
00575 }
00576 if (work_area.height < MIN_SANE_AREA)
00577 {
00578 meta_warning ("struts occupy an unusually large percentage of the screen; "
00579 "available remaining height = %d < %d",
00580 work_area.height, MIN_SANE_AREA);
00581 if (work_area.height < 1)
00582 {
00583 work_area.y = (workspace->screen->rect.height - MIN_SANE_AREA)/2;
00584 work_area.height = MIN_SANE_AREA;
00585 }
00586 else
00587 {
00588 int amount = (MIN_SANE_AREA - work_area.height)/2;
00589 work_area.y -= amount;
00590 work_area.height += 2*amount;
00591 }
00592 }
00593 workspace->work_area_screen = work_area;
00594 meta_topic (META_DEBUG_WORKAREA,
00595 "Computed work area for workspace %d: %d,%d %d x %d\n",
00596 meta_workspace_index (workspace),
00597 workspace->work_area_screen.x,
00598 workspace->work_area_screen.y,
00599 workspace->work_area_screen.width,
00600 workspace->work_area_screen.height);
00601
00602
00603 g_free (workspace->work_area_xinerama);
00604 workspace->work_area_xinerama = g_new (MetaRectangle,
00605 workspace->screen->n_xinerama_infos);
00606
00607 for (i = 0; i < workspace->screen->n_xinerama_infos; i++)
00608 {
00609 work_area = workspace->screen->xinerama_infos[i].rect;
00610
00611 if (workspace->xinerama_region[i] == NULL)
00612
00613
00614
00615 work_area = meta_rect (work_area.x, work_area.y, -1, -1);
00616 else
00617 meta_rectangle_clip_to_region (workspace->xinerama_region[i],
00618 FIXED_DIRECTION_NONE,
00619 &work_area);
00620
00621 workspace->work_area_xinerama[i] = work_area;
00622 meta_topic (META_DEBUG_WORKAREA,
00623 "Computed work area for workspace %d "
00624 "xinerama %d: %d,%d %d x %d\n",
00625 meta_workspace_index (workspace),
00626 i,
00627 workspace->work_area_xinerama[i].x,
00628 workspace->work_area_xinerama[i].y,
00629 workspace->work_area_xinerama[i].width,
00630 workspace->work_area_xinerama[i].height);
00631 }
00632
00633
00634
00635
00636 if (workspace->screen_region == NULL)
00637 {
00638 MetaRectangle *nonempty_region;
00639 nonempty_region = g_new (MetaRectangle, 1);
00640 *nonempty_region = workspace->work_area_screen;
00641 workspace->screen_region = g_list_prepend (NULL, nonempty_region);
00642 }
00643
00644
00645 g_assert (workspace->screen_edges == NULL);
00646 g_assert (workspace->xinerama_edges == NULL);
00647 workspace->screen_edges =
00648 meta_rectangle_find_onscreen_edges (&workspace->screen->rect,
00649 workspace->all_struts);
00650 tmp = NULL;
00651 for (i = 0; i < workspace->screen->n_xinerama_infos; i++)
00652 tmp = g_list_prepend (tmp, &workspace->screen->xinerama_infos[i].rect);
00653 workspace->xinerama_edges =
00654 meta_rectangle_find_nonintersected_xinerama_edges (tmp,
00655 workspace->all_struts);
00656 g_list_free (tmp);
00657
00658
00659 workspace->work_areas_invalid = FALSE;
00660 }
00661
00662 void
00663 meta_workspace_get_work_area_for_xinerama (MetaWorkspace *workspace,
00664 int which_xinerama,
00665 MetaRectangle *area)
00666 {
00667 g_assert (which_xinerama >= 0);
00668
00669 ensure_work_areas_validated (workspace);
00670 g_assert (which_xinerama < workspace->screen->n_xinerama_infos);
00671
00672 *area = workspace->work_area_xinerama[which_xinerama];
00673 }
00674
00675 void
00676 meta_workspace_get_work_area_all_xineramas (MetaWorkspace *workspace,
00677 MetaRectangle *area)
00678 {
00679 ensure_work_areas_validated (workspace);
00680
00681 *area = workspace->work_area_screen;
00682 }
00683
00684 GList*
00685 meta_workspace_get_onscreen_region (MetaWorkspace *workspace)
00686 {
00687 ensure_work_areas_validated (workspace);
00688
00689 return workspace->screen_region;
00690 }
00691
00692 GList*
00693 meta_workspace_get_onxinerama_region (MetaWorkspace *workspace,
00694 int which_xinerama)
00695 {
00696 ensure_work_areas_validated (workspace);
00697
00698 return workspace->xinerama_region[which_xinerama];
00699 }
00700
00701 #ifdef WITH_VERBOSE_MODE
00702 static char *
00703 meta_motion_direction_to_string (MetaMotionDirection direction)
00704 {
00705 switch (direction)
00706 {
00707 case META_MOTION_UP:
00708 return "Up";
00709 case META_MOTION_DOWN:
00710 return "Down";
00711 case META_MOTION_LEFT:
00712 return "Left";
00713 case META_MOTION_RIGHT:
00714 return "Right";
00715 }
00716
00717 return "Unknown";
00718 }
00719 #endif
00720
00721 MetaWorkspace*
00722 meta_workspace_get_neighbor (MetaWorkspace *workspace,
00723 MetaMotionDirection direction)
00724 {
00725 MetaWorkspaceLayout layout;
00726 int i, current_space, num_workspaces;
00727 gboolean ltr;
00728
00729 current_space = meta_workspace_index (workspace);
00730 num_workspaces = meta_screen_get_n_workspaces (workspace->screen);
00731 meta_screen_calc_workspace_layout (workspace->screen, num_workspaces,
00732 current_space, &layout);
00733
00734 meta_verbose ("Getting neighbor of %d in direction %s\n",
00735 current_space, meta_motion_direction_to_string (direction));
00736
00737 ltr = meta_ui_get_direction() == META_UI_DIRECTION_LTR;
00738
00739 switch (direction)
00740 {
00741 case META_MOTION_LEFT:
00742 layout.current_col -= ltr ? 1 : -1;
00743 break;
00744 case META_MOTION_RIGHT:
00745 layout.current_col += ltr ? 1 : -1;
00746 break;
00747 case META_MOTION_UP:
00748 layout.current_row -= 1;
00749 break;
00750 case META_MOTION_DOWN:
00751 layout.current_row += 1;
00752 break;
00753 }
00754
00755 if (layout.current_col < 0)
00756 layout.current_col = 0;
00757 if (layout.current_col >= layout.cols)
00758 layout.current_col = layout.cols - 1;
00759 if (layout.current_row < 0)
00760 layout.current_row = 0;
00761 if (layout.current_row >= layout.rows)
00762 layout.current_row = layout.rows - 1;
00763
00764 i = layout.grid[layout.current_row * layout.cols + layout.current_col];
00765
00766 if (i < 0)
00767 i = current_space;
00768
00769 if (i >= num_workspaces)
00770 meta_bug ("calc_workspace_layout left an invalid (too-high) workspace number %d in the grid\n",
00771 i);
00772
00773 meta_verbose ("Neighbor workspace is %d at row %d col %d\n",
00774 i, layout.current_row, layout.current_col);
00775
00776 meta_screen_free_workspace_layout (&layout);
00777
00778 return meta_screen_get_workspace_by_index (workspace->screen, i);
00779 }
00780
00781 const char*
00782 meta_workspace_get_name (MetaWorkspace *workspace)
00783 {
00784 return meta_prefs_get_workspace_name (meta_workspace_index (workspace));
00785 }
00786
00787 void
00788 meta_workspace_focus_default_window (MetaWorkspace *workspace,
00789 MetaWindow *not_this_one,
00790 guint32 timestamp)
00791 {
00792 if (timestamp == CurrentTime)
00793 {
00794 meta_warning ("CurrentTime used to choose focus window; "
00795 "focus window may not be correct.\n");
00796 }
00797
00798
00799 if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK ||
00800 !workspace->screen->display->mouse_mode)
00801 focus_ancestor_or_mru_window (workspace, not_this_one, timestamp);
00802 else
00803 {
00804 MetaWindow * window;
00805 window = meta_screen_get_mouse_window (workspace->screen, not_this_one);
00806 if (window &&
00807 window->type != META_WINDOW_DOCK &&
00808 window->type != META_WINDOW_DESKTOP)
00809 {
00810 if (timestamp == CurrentTime)
00811 {
00812
00813
00814
00815
00816
00817
00818
00819
00820 meta_topic (META_DEBUG_FOCUS,
00821 "Not focusing mouse window %s because EnterNotify events should handle that\n", window->desc);
00822 }
00823 else
00824 {
00825 meta_topic (META_DEBUG_FOCUS,
00826 "Focusing mouse window %s\n", window->desc);
00827 meta_window_focus (window, timestamp);
00828 }
00829
00830 if (workspace->screen->display->autoraise_window != window &&
00831 meta_prefs_get_auto_raise ())
00832 {
00833 meta_display_queue_autoraise_callback (workspace->screen->display,
00834 window);
00835 }
00836 }
00837 else if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_SLOPPY)
00838 focus_ancestor_or_mru_window (workspace, not_this_one, timestamp);
00839 else if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_MOUSE)
00840 {
00841 meta_topic (META_DEBUG_FOCUS,
00842 "Setting focus to no_focus_window, since no valid "
00843 "window to focus found.\n");
00844 meta_display_focus_the_no_focus_window (workspace->screen->display,
00845 workspace->screen,
00846 timestamp);
00847 }
00848 }
00849 }
00850
00851 static gboolean
00852 record_ancestor (MetaWindow *window,
00853 void *data)
00854 {
00855 MetaWindow **result = data;
00856
00857 *result = window;
00858 return FALSE;
00859 }
00860
00861
00862
00863
00864 static void
00865 focus_ancestor_or_mru_window (MetaWorkspace *workspace,
00866 MetaWindow *not_this_one,
00867 guint32 timestamp)
00868 {
00869 MetaWindow *window = NULL;
00870 MetaWindow *desktop_window = NULL;
00871 GList *tmp;
00872
00873 if (not_this_one)
00874 meta_topic (META_DEBUG_FOCUS,
00875 "Focusing MRU window excluding %s\n", not_this_one->desc);
00876 else
00877 meta_topic (META_DEBUG_FOCUS,
00878 "Focusing MRU window\n");
00879
00880
00881 if (not_this_one)
00882 {
00883 MetaWindow *ancestor;
00884 ancestor = NULL;
00885 meta_window_foreach_ancestor (not_this_one, record_ancestor, &ancestor);
00886 if (ancestor != NULL)
00887 {
00888 meta_topic (META_DEBUG_FOCUS,
00889 "Focusing %s, ancestor of %s\n",
00890 ancestor->desc, not_this_one->desc);
00891
00892 meta_window_focus (ancestor, timestamp);
00893
00894
00895 if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK)
00896 meta_window_raise (ancestor);
00897
00898 return;
00899 }
00900 }
00901
00902
00903 tmp = workspace->mru_list;
00904
00905 while (tmp)
00906 {
00907 MetaWindow* tmp_window;
00908 tmp_window = ((MetaWindow*) tmp->data);
00909 if (tmp_window != not_this_one &&
00910 meta_window_showing_on_its_workspace (tmp_window) &&
00911 tmp_window->type != META_WINDOW_DOCK &&
00912 tmp_window->type != META_WINDOW_DESKTOP)
00913 {
00914 window = tmp->data;
00915 break;
00916 }
00917 else if (tmp_window != not_this_one &&
00918 desktop_window == NULL &&
00919 meta_window_showing_on_its_workspace (tmp_window) &&
00920 tmp_window->type == META_WINDOW_DESKTOP)
00921 {
00922
00923 desktop_window = tmp_window;
00924 }
00925
00926 tmp = tmp->next;
00927 }
00928
00929
00930 if (window == NULL)
00931 window = desktop_window;
00932
00933 if (window)
00934 {
00935 meta_topic (META_DEBUG_FOCUS,
00936 "Focusing workspace MRU window %s\n", window->desc);
00937
00938 meta_window_focus (window, timestamp);
00939
00940
00941 if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK)
00942 meta_window_raise (window);
00943 }
00944 else
00945 {
00946 meta_topic (META_DEBUG_FOCUS, "No MRU window to focus found; focusing no_focus_window.\n");
00947 meta_display_focus_the_no_focus_window (workspace->screen->display,
00948 workspace->screen,
00949 timestamp);
00950 }
00951 }