static void clientCycleActivate (Client *c) { ScreenInfo *screen_info; DisplayInfo *display_info; Client *focused; guint workspace; if (c == NULL) { return; } screen_info = c->screen_info; display_info = screen_info->display_info; workspace = c->win_workspace; focused = clientGetFocus (); if ((focused) && (c != focused)) { /* We might be able to avoid this if we are about to switch workspace */ clientAdjustFullscreenLayer (focused, FALSE); } if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_WAS_SHOWN)) { /* We are explicitely activating a window that was shown before show-desktop */ clientClearAllShowDesktop (screen_info); } if (workspace != screen_info->current_ws) { workspaceSwitch (screen_info, workspace, c, FALSE, myDisplayGetCurrentTime (display_info)); } clientCycleFocusAndRaise (c); }
void clientFocusDirection (Client * c, int dir) { Client *c2, *n = NULL; guint i; gint diff = 0, cur = 1024 * 1024; g_return_if_fail (c); TRACE ("entering focus direction"); for (c2 = c->next, i = 1; c && i < c->screen_info->client_count; i++, c2 = c2->next) { if (!clientSelectMask (c2, NULL, 0, WINDOW_REGULAR_FOCUSABLE)) { TRACE ("%s not in select mask", c2->name); continue; } switch (dir) { case FOCUS_UP: diff = c->y - c2->y; break; case FOCUS_DOWN: diff = c2->y - c->y; break; case FOCUS_LEFT: diff = c->x - c2->x; break; case FOCUS_RIGHT: diff = c2->x - c->x; break; } if (diff > 0 && cur > diff) { cur = diff; n = c2; } } if (n) { clientSetFocus (c->screen_info, n, myDisplayGetCurrentTime (c->screen_info->display_info), NO_FOCUS_FLAG); } }
void clientPassFocus (ScreenInfo *screen_info, Client *c, GList *exclude_list) { DisplayInfo *display_info; ClientPair top_most; Client *new_focus; Client *current_focus; Window dr, window; unsigned int mask; int rx, ry, wx, wy; int look_in_layer; TRACE ("entering"); look_in_layer = (c ? c->win_layer : WIN_LAYER_NORMAL); new_focus = NULL; current_focus = client_focus; if (pending_focus) { current_focus = pending_focus; } if ((c || current_focus) && (c != current_focus)) { return; } display_info = screen_info->display_info; top_most = clientGetTopMostFocusable (screen_info, look_in_layer, exclude_list); if (!(screen_info->params->click_to_focus) && XQueryPointer (myScreenGetXDisplay (screen_info), screen_info->xroot, &dr, &window, &rx, &ry, &wx, &wy, &mask)) { new_focus = clientAtPosition (screen_info, rx, ry, exclude_list); } if (!new_focus) { new_focus = top_most.prefered ? top_most.prefered : top_most.highest; } clientSetFocus (screen_info, new_focus, myDisplayGetCurrentTime (display_info), FOCUS_IGNORE_MODAL | FOCUS_FORCE | FOCUS_TRANSITION); }
void workspaceSetCount (ScreenInfo * screen_info, guint count) { DisplayInfo *display_info; Client *c; GList *list; g_return_if_fail (screen_info != NULL); TRACE ("entering workspaceSetCount"); if (count < 1) { count = 1; } if (count == screen_info->workspace_count) { return; } display_info = screen_info->display_info; setHint (display_info, screen_info->xroot, NET_NUMBER_OF_DESKTOPS, count); screen_info->workspace_count = count; for (list = screen_info->windows_stack; list; list = g_list_next (list)) { c = (Client *) list->data; if (c->win_workspace > count - 1) { clientSetWorkspace (c, count - 1, TRUE); } } if (screen_info->current_ws > count - 1) { workspaceSwitch (screen_info, count - 1, NULL, TRUE, myDisplayGetCurrentTime (display_info)); } setNetWorkarea (display_info, screen_info->xroot, screen_info->workspace_count, screen_info->logical_width, screen_info->logical_height, screen_info->margins); /* Recompute the layout based on the (changed) number of desktops */ getDesktopLayout (display_info, screen_info->xroot, screen_info->workspace_count, &screen_info->desktop_layout); }
static void clientCycleFocusAndRaise (Client *c) { ScreenInfo *screen_info; DisplayInfo *display_info; Client *ancestor; g_return_if_fail (c != NULL); TRACE ("client \"%s\" (0x%lx)", c->name, c->window); screen_info = c->screen_info; display_info = screen_info->display_info; ancestor = clientGetTransientFor(c); clientRaise (c, None); clientShow (ancestor, TRUE); clientUnshade (c); clientSetFocus (screen_info, c, myDisplayGetCurrentTime (display_info), NO_FOCUS_FLAG); clientSetLastRaise (c); }
static void clientCycleFocusAndRaise (Client *c) { ScreenInfo *screen_info; DisplayInfo *display_info; Client *sibling; g_return_if_fail (c != NULL); TRACE ("entering clientFocusAndRaise"); screen_info = c->screen_info; display_info = screen_info->display_info; sibling = clientGetTransientFor(c); clientRaise (sibling, None); clientShow (sibling, TRUE); clientUnshade (c); clientSetFocus (screen_info, c, myDisplayGetCurrentTime (display_info), NO_FOCUS_FLAG); clientSetLastRaise (c); }
gboolean clientFocusNew(Client * c) { ScreenInfo *screen_info; DisplayInfo *display_info; gboolean give_focus; gboolean prevent_focus_stealing; gboolean prevented; g_return_val_if_fail (c != NULL, FALSE); screen_info = c->screen_info; display_info = screen_info->display_info; give_focus = (c-> type & WINDOW_REGULAR_FOCUSABLE) && (screen_info->params->focus_new); prevent_focus_stealing = screen_info->params->prevent_focus_stealing; prevented = FALSE; /* Try to avoid focus stealing */ if (!clientAcceptFocus (c) || (c->type & WINDOW_TYPE_DONT_FOCUS)) { give_focus = FALSE; } else if (FLAG_TEST (c->flags, CLIENT_FLAG_HAS_USER_TIME) && (c->user_time == (guint32) 0)) { /* * _NET_WM_USER_TIME definition from http://standards.freedesktop.org/wm-spec * [...] "The special value of zero on a newly mapped window can be used to * request that the window not be initially focused when it is mapped." */ TRACE ("given startup time is nil, not focusing \"%s\"", c->name); give_focus = FALSE; prevented = FALSE; } else if ((client_focus) && (prevent_focus_stealing)) { if (client_focus->win_layer > c->win_layer) { TRACE ("not focusing \"%s\" because the current focused window is on a upper layer", c->name); give_focus = FALSE; prevented = TRUE; } else if (client_focus->win_layer < c->win_layer) { /* We don't use focus stealing prevention against upper layers */ TRACE ("ignoring startup prevention because the current focused window is on a lower layer"); give_focus = TRUE; prevented = FALSE; } else if (FLAG_TEST (client_focus->xfwm_flags, XFWM_FLAG_MOVING_RESIZING)) { give_focus = FALSE; prevented = TRUE; } else if (FLAG_TEST (c->flags, CLIENT_FLAG_HAS_STARTUP_TIME | CLIENT_FLAG_HAS_USER_TIME)) { TRACE ("current time is %u, time for \"%s\" is %u", (unsigned int) client_focus->user_time, c->name, (unsigned int) c->user_time); if (TIMESTAMP_IS_BEFORE (c->user_time, client_focus->user_time)) { give_focus = FALSE; prevented = TRUE; } } } if (FLAG_TEST(c->flags, CLIENT_FLAG_STATE_MODAL)) { give_focus = TRUE; } if (give_focus) { if (client_focus) { clientAdjustFullscreenLayer (client_focus, FALSE); } clientRaise (c, None); clientShow (c, TRUE); clientSetFocus (screen_info, c, myDisplayGetCurrentTime (display_info), FOCUS_IGNORE_MODAL); } else { Client *c2 = clientGetFocus(); clientSortRing(c); if ((c2 != NULL) && (c2->win_layer == c->win_layer) && prevented) { /* * Place windows under the currently focused only if focus * stealing prevention had prevented the focus transition, * otherwise, leave the unfocused window on top. */ clientLower (c, c2->frame); } else { clientRaise (c, None); } clientSortRing(c2); if (prevented) { TRACE ("setting WM_STATE_DEMANDS_ATTENTION flag on \"%s\" (0x%lx)", c->name, c->window); FLAG_SET (c->flags, CLIENT_FLAG_DEMANDS_ATTENTION); } clientShow (c, TRUE); clientSetNetState (c); } return (give_focus); }
void clientCycle (Client * c, XfwmEventKey *event) { ScreenInfo *screen_info; DisplayInfo *display_info; ClientCycleData passdata; GList *client_list, *selected; int key, modifier; g_return_if_fail (c != NULL); TRACE ("client \"%s\" (0x%lx)", c->name, c->window); screen_info = c->screen_info; display_info = screen_info->display_info; client_list = clientCycleCreateList (c); if (!client_list) { return; } modifier = 0; key = myScreenGetKeyPressed (screen_info, event); if (key == KEY_CYCLE_REVERSE_WINDOWS) { selected = g_list_last (client_list); modifier = screen_info->params->keys[KEY_CYCLE_REVERSE_WINDOWS].modifier; } else { selected = g_list_next (client_list); modifier = screen_info->params->keys[KEY_CYCLE_WINDOWS].modifier; } if (!selected) { /* Only one element in list */ selected = client_list; } if (!modifier) { /* * The shortcut has no modifier so there's no point in entering * the cycle loop, just select the next or previous window and * that's it... */ clientCycleActivate ((Client *) selected->data); g_list_free (client_list); return; } myScreenGrabPointer (screen_info, TRUE, EnterWindowMask | LeaveWindowMask, None, event->time); /* Grabbing the pointer may fail e.g. if the user is doing a drag'n drop */ if (!myScreenGrabKeyboard (screen_info, KeyPressMask | KeyReleaseMask, event->time)) { TRACE ("grab failed in clientCycle"); myDisplayBeep (display_info); myScreenUngrabKeyboard (screen_info, myDisplayGetCurrentTime (display_info)); myScreenUngrabPointer (screen_info, myDisplayGetCurrentTime (display_info)); g_list_free (client_list); return; } passdata.wireframe = NULL; passdata.inside = FALSE; TRACE ("entering cycle loop"); if (screen_info->params->cycle_raise) { clientRaise ((Client *) selected->data, None); } if (screen_info->params->cycle_draw_frame) { passdata.wireframe = wireframeCreate ((Client *) selected->data); } passdata.tabwin = tabwinCreate (&client_list, selected, screen_info->params->cycle_workspaces); eventFilterPush (display_info->xfilter, clientCycleEventFilter, &passdata); gtk_main (); eventFilterPop (display_info->xfilter); TRACE ("leaving cycle loop"); if (passdata.wireframe) { wireframeDelete (passdata.wireframe); } updateXserverTime (display_info); c = tabwinGetSelected (passdata.tabwin); if (c) { clientCycleActivate (c); } tabwinDestroy (passdata.tabwin); g_free (passdata.tabwin); g_list_free (client_list); if (passdata.inside) { /* A bit of a hack, flush EnterNotify if the pointer is inside * the tabwin to defeat focus-follow-mouse tracking */ eventFilterPush (display_info->xfilter, clientCycleFlushEventFilter, display_info); gtk_main (); eventFilterPop (display_info->xfilter); } myScreenUngrabKeyboard (screen_info, myDisplayGetCurrentTime (display_info)); myScreenUngrabPointer (screen_info, myDisplayGetCurrentTime (display_info)); }
void clientCycle (Client * c, XKeyEvent * ev) { ScreenInfo *screen_info; DisplayInfo *display_info; ClientCycleData passdata; GList *client_list, *selected; gboolean g1, g2; int key, modifier; Client *c2; g_return_if_fail (c != NULL); TRACE ("entering clientCycle"); screen_info = c->screen_info; display_info = screen_info->display_info; client_list = clientCycleCreateList (c); if (!client_list) { return; } modifier = 0; key = myScreenGetKeyPressed (screen_info, ev); if (key == KEY_CYCLE_REVERSE_WINDOWS) { selected = g_list_last (client_list); modifier = screen_info->params->keys[KEY_CYCLE_REVERSE_WINDOWS].modifier; } else { selected = g_list_next (client_list); modifier = screen_info->params->keys[KEY_CYCLE_WINDOWS].modifier; } if (!selected) { /* Only one element in list */ selected = client_list; } if (!modifier) { /* * The shortcut has no modifier so there's no point in entering * the cycle loop, just select the next or previous window and * that's it... */ clientCycleActivate ((Client *) selected->data); g_list_free (client_list); return; } g1 = myScreenGrabKeyboard (screen_info, ev->time); g2 = myScreenGrabPointer (screen_info, TRUE, LeaveWindowMask, None, ev->time); if (!g1 || !g2) { TRACE ("grab failed in clientCycle"); gdk_beep (); myScreenUngrabKeyboard (screen_info, myDisplayGetCurrentTime (display_info)); myScreenUngrabPointer (screen_info, myDisplayGetCurrentTime (display_info)); g_list_free (client_list); return; } passdata.wireframe = None; TRACE ("entering cycle loop"); if (screen_info->params->cycle_draw_frame) { passdata.wireframe = wireframeCreate ((Client *) selected->data); } passdata.tabwin = tabwinCreate (&client_list, selected, screen_info->params->cycle_workspaces); eventFilterPush (display_info->xfilter, clientCycleEventFilter, &passdata); c2 = myScreenGetClientFromWindow (screen_info, GDK_WINDOW_XID (gtk_widget_get_window ( passdata.tabwin->tabwin_list->data)), SEARCH_FRAME); g_message ("%p", c2); clientSetFocus (screen_info, c2, ev->time, NO_FOCUS_FLAG); gtk_main (); eventFilterPop (display_info->xfilter); TRACE ("leaving cycle loop"); if (passdata.wireframe) { wireframeDelete (screen_info, passdata.wireframe); } updateXserverTime (display_info); c = tabwinGetSelected (passdata.tabwin); if (c) { clientCycleActivate (c); } tabwinDestroy (passdata.tabwin); g_free (passdata.tabwin); g_list_free (client_list); myScreenUngrabKeyboard (screen_info, myDisplayGetCurrentTime (display_info)); myScreenUngrabPointer (screen_info, myDisplayGetCurrentTime (display_info)); }