void list_restack(unsigned long *body, unsigned long length) { PagerWindow *t; Window target_w; Window *wins; int i, j, d; wins = (Window *) safemalloc (length * sizeof (Window)); /* first restack in the icon view */ j = 0; for (i = 0; i < (length - FvwmPacketHeaderSize); i += 3) { target_w = body[i]; t = Start; while((t!= NULL)&&(t->w != target_w)) { t = t->next; } if (t != NULL) { wins[j++] = t->IconView; } } XRestackWindows(dpy, wins, j); /* now restack each desk separately, since they have separate roots */ for (d = 0; d < ndesks; d++) { j = 0; for (i = 0; i < (length - 4); i+=3) { target_w = body[i]; t = Start; while((t!= NULL)&&((t->w != target_w)||(t->desk != d+desk1))) { t = t->next; } if (t != NULL) { if (t->PagerView != None) { wins[j++] = t->PagerView; } } } XRestackWindows(dpy, wins, j); } free (wins); }
bool ThemeEngine::x11Event( XEvent* e ) { if( e->type != ConfigureNotify && e->type != MapNotify ) return false; if( e->type == ConfigureNotify && e->xconfigure.event != qt_xrootwin()) return false; if( e->type == MapNotify && e->xmap.event != qt_xrootwin()) return false; if( d->mSplashWindows.count() == 0 ) return false; // this restacking is written in a way so that // if the stacking positions actually don't change, // all restacking operations will be no-op, // and no ConfigureNotify will be generated, // thus avoiding possible infinite loops XRaiseWindow( qt_xdisplay(), d->mSplashWindows.first()); // raise topmost // and stack others below it Window* stack = new Window[ d->mSplashWindows.count() ]; int count = 0; for( QValueList< Window >::ConstIterator it = d->mSplashWindows.begin(); it != d->mSplashWindows.end(); ++it ) stack[ count++ ] = *it; XRestackWindows( x11Display(), stack, count ); delete[] stack; return false; }
/* * Class: XlibWrapper * Method: XRestackWindows * Signature: (JJI)V */ JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XRestackWindows (JNIEnv *env, jclass clazz, jlong display, jlong windows, jint length) { AWT_CHECK_HAVE_LOCK(); XRestackWindows( (Display *)display,(Window*) windows, length); }
// raise all windows in a tag void tag_raise(unsigned int tag) { int i, found = 0, shaded = 0; Window w; client *c; winlist *stack; // if this tag was previously hidden, reveal it clients_ascend(windows_shaded, i, w, c) if (c->manage && c->cache->tags & tag) { client_reveal(c); shaded++; } if (shaded) { XSync(display, False); reset_cache_xattr(); reset_cache_client(); reset_cache_inplay(); } stack = winlist_new(); // locate windows with _NET_WM_STATE_ABOVE and _NET_WM_STATE_STICKY managed_descend(i, w, c) if (winlist_find(stack, w) < 0 && c->visible && c->trans == None && client_has_state(c, netatoms[_NET_WM_STATE_ABOVE]) && client_has_state(c, netatoms[_NET_WM_STATE_STICKY])) client_stack_family(c, stack); // locate windows with _NET_WM_STATE_ABOVE in this tag tag_descend(i, w, c, tag) if (winlist_find(stack, w) < 0 && c->visible && c->trans == None && client_has_state(c, netatoms[_NET_WM_STATE_ABOVE])) { client_stack_family(c, stack); found++; } // locate _NET_WM_WINDOW_TYPE_DOCK windows clients_descend(windows_in_play(), i, w, c) if (winlist_find(stack, w) < 0 && c->visible && c->trans == None && c->type == netatoms[_NET_WM_WINDOW_TYPE_DOCK]) client_stack_family(c, stack); // locate all other windows in the tag tag_descend(i, w, c, tag) if (winlist_find(stack, w) < 0 && c->trans == None) { client_stack_family(c, stack); found++; } // raise the top window in the stack if (stack->len) XRaiseWindow(display, stack->array[0]); // stack everything else, in order, underneath top window if (stack->len > 1) XRestackWindows(display, stack->array, stack->len); winlist_free(stack); tag_set_current(tag); if (config_only_auto) tag_only(tag); // focus the last-focused client in the tag clients_descend(windows_activated, i, w, c) if (c->cache->tags & tag) { client_activate(c, RAISE, WARPDEF); break; } // in case no windows are in the tag, show some activity if (found) notice("Tag %d", tag_to_desktop(tag)+1); else notice("Tag %d (empty!)", tag_to_desktop(tag)+1); }
void WindowManager::restack_windows() { Window *windows = new Window[1]; int total=0; DBG("Restack: DOCK, SPLASH"); for(uint n=0; n<stack_order.size(); n++) { Frame *f = stack_order[n]; if(f->window_type()==TYPE_DOCK || f->window_type()==TYPE_SPLASH) { windows = (Window*)realloc(windows, (total+1)*sizeof(Window)); windows[total++] = fl_xid(f); } } DBG("Restack: TOOLBAR, MENU"); for(uint n=0; n<stack_order.size(); n++) { Frame *f = stack_order[n]; if(f->window_type()==TYPE_TOOLBAR || f->window_type()==TYPE_MENU) { windows = (Window*)realloc(windows, (total+1)*sizeof(Window)); windows[total++] = fl_xid(f); } } DBG("Restack: NORMAL, UTIL, DIALOG"); for(uint n=stack_order.size(); n--;) { Frame *f = stack_order[n]; if( (f->window_type()==TYPE_NORMAL || f->window_type()==TYPE_UTIL || f->window_type()==TYPE_DIALOG) && f->state()==NORMAL ) { windows = (Window*)realloc(windows, (total+1)*sizeof(Window)); windows[total++] = fl_xid(f); } } DBG("Restack: DESKTOP"); for(uint n=0; n<stack_order.size(); n++) { Frame *f = stack_order[n]; if(f->window_type()==TYPE_DESKTOP) { windows = (Window*)realloc(windows, (total+1)*sizeof(Window)); windows[total++] = fl_xid(f); } } DBG("Restack: Call XRestackWindows!"); if(total) XRestackWindows(fl_display, windows, total); delete []windows; }
int raiseWindow(Display *display, Window window) { Window parent, root, *children, *neworder; unsigned int nchildren, i, rotate; XWindowAttributes attr; if (!XQueryTree(display, DefaultRootWindow(display), &root, &parent, &children, &nchildren)) return 1; if (!children) return 2; for (rotate = 0; rotate < nchildren; ++rotate) { if (children[nchildren-1 - rotate] == window) break; } if (rotate == nchildren) { XFree(children); return 2; } if (rotate > 0) { /* Unmap and remap the old top-level window to kill off any mouse and * keyboard hooks */ XUnmapWindow(display, children[nchildren-1]); neworder = (Window*)malloc(nchildren * sizeof(*neworder)); /* XQueryTree returns children in back-to-front order, while * XRestackWindows takes a front-to-back list. Reverse the order and * rotate the position of the children -n positions to put the requested * window into the first position in the list. */ for (i = 0; i < nchildren; ++i) { neworder[nchildren-1 - ((i+rotate) % nchildren)] = children[i]; } XRestackWindows(display, neworder, nchildren); free(neworder); /* Split the map from the unmap to reduce the number of events */ XMapWindow(display, children[nchildren-1]); } XFree(children); if (!XGetWindowAttributes(display, DefaultRootWindow(display), &attr)) { return 1; } /* Twiddle the width of the window to force a full refresh */ XMoveResizeWindow(display, window, attr.x, attr.y, attr.width-1, attr.height); XMoveResizeWindow(display, window, attr.x, attr.y, attr.width, attr.height); return 0; }
static bool referenceRestack(const T &subset, Window **childrenp=NULL, unsigned *nchildrenp=NULL) { int n = subset.count(); WindowVec reversed(n); for (int i = 0; i < n; i++) reversed[n-1-i] = subset[i]; Q_ASSERT(Dpy != NULL); if (!XRestackWindows(Dpy, (Window*)reversed.constData(), reversed.count())) qFatal("XRestackWindows() failed"); return verifyTree(subset, childrenp, nchildrenp); }
void stacking_restore(void) { Window *win; GList *it; gint i; gulong start; win = g_new(Window, g_list_length(stacking_list) + 1); win[0] = screen_support_win; for(i = 1, it = stacking_list; it; ++i, it = g_list_next(it)) win[i] = window_top(it->data); start = event_start_ignore_all_enters(); XRestackWindows(t_display, win, i); event_end_ignore_all_enters(start); g_free(win); pause_changes = FALSE; }
static void raiseWindow(WSwitchPanel * swpanel, WWindow * wwin) { Window swwin = wSwitchPanelGetWindow(swpanel); if (wwin->flags.mapped) { if (swwin != None) { Window win[2]; win[0] = swwin; win[1] = wwin->frame->core->window; XRestackWindows(dpy, win, 2); } else XRaiseWindow(dpy, wwin->frame->core->window); } }
/** * Raise electric border windows to the real top of the screen. We only need * to do this if an effect input window is active. */ void Workspace::raiseElectricBorderWindows() { Window* windows = new Window[ 8 ]; // There are up to 8 borders int pos = 0; for( int i = 0; i < ELECTRIC_COUNT; ++i ) if( electric_windows[ i ] != None ) windows[ pos++ ] = electric_windows[ i ]; if( !pos ) { delete [] windows; return; // No borders at all } XRaiseWindow( display(), windows[ 0 ] ); XRestackWindows( display(), windows, pos ); delete [] windows; }
void RaiseMlvwmWindow( MlvwmWindow *win ) { MlvwmWindow *tmp, *lastwin=NULL; int count=4, set=3; Window *wins; for( tmp = Scr.MlvwmRoot.next; tmp!=NULL; tmp=tmp->next ){ if( tmp->flags&TRANSIENT && tmp->transientfor==win->w && tmp!=win && !(tmp->flags&ONTOP) ) count++; if( tmp->flags&ONTOP && tmp!=win ) count++; if( tmp->next==NULL ) lastwin = tmp; } wins = calloc( count, sizeof(Window) ); wins[0] = Scr.MenuBar; wins[1] = Scr.lbCorner; wins[2] = Scr.rbCorner; for( tmp = Scr.MlvwmRoot.next; tmp!=NULL; tmp=tmp->next ){ if( win->flags&TRANSIENT && win->transientfor==tmp->w && tmp->flags&ONTOP ){ wins[set++] = win->frame; } if( tmp!=win && tmp->flags&ONTOP ) wins[set++] = tmp->frame; } for( tmp = lastwin; tmp!=&Scr.MlvwmRoot; tmp=tmp->prev ) if( tmp->flags&TRANSIENT && tmp->transientfor==win->w && tmp!=win && !(tmp->flags&ONTOP)) wins[set++] = tmp->frame; if( count!=set ) wins[set++] = win->frame; XRaiseWindow( dpy, wins[0] ); XRaiseWindow( dpy, wins[1] ); XRaiseWindow( dpy, wins[2] ); XRestackWindows( dpy, wins, set ); free( wins ); }
void stacking_temp_raise(struct wm_window *window) { Window win[2]; GList *it; gulong start; g_assert(window_layer(window) < WM_STACKING_LAYER_INTERNAL); win[0] = screen_support_win; for(it = stacking_list; it; it = g_list_next(it)) { struct wm_window *w = it->data; if(window_layer(w) >= WM_STACKING_LAYER_INTERNAL) win[0] = window_top(w); else break; } win[1] = window_top(window); start = event_start_ignore_all_enters(); XRestackWindows(t_display, win, 2); event_end_ignore_all_enters(start); pause_changes = TRUE; }
static void do_restack(GList *wins, GList *before) { GList *it; Window *win; gint i; #ifdef DEBUG GList *next; g_assert(wins); for(it = wins; it; it = next) { next = g_list_next(it); if(!next) break; g_assert(window_layer(it->data) == window_layer(next->data)); } if(before) g_assert(window_layer(it->data) >= window_layer(before->data)); #endif win = g_new(Window, g_list_length(wins) + 1); if(before == stacking_list) win[0] = screen_support_win; else if(!before) win[0] = window_top(g_list_last(stacking_list)->data); else win[0] = window_top(g_list_previous(before)->data); for(i = 1, it = wins; it; ++i, it = g_list_next(it)) { win[i] = window_top(it->data); g_assert(win[i] != None); stacking_list = g_list_insert_before(stacking_list, before, it->data); } #ifdef DEBUG for(it = stacking_list;; it = next) { next = g_list_next(it); if(!next) break; g_assert(window_layer(it->data) >= window_layer(next->data)); } #endif if(!pause_changes) XRestackWindows(t_display, win, i); g_free(win); }
static DWORD DrvStackingOrder(LPARAM dwParm1, LPARAM dwParm2, LPVOID lpStruct) { HWND hWndInsertAfter = (HWND)dwParm1; HWND WinAfter = (HWND)dwParm2; Window win = (Window)lpStruct; Window win_restack[2]; PRIVATEDISPLAY *Disp = GETDP(); int nFunc = (int)hWndInsertAfter; switch (nFunc) { case (int)HWND_TOP: #ifdef LATER /* this should be resolved at the upper level */ #else case (int)HWND_TOPMOST: #endif XRaiseWindow(Disp->display, win); break; case (int)HWND_BOTTOM: #ifdef LATER /* this should be resolved at the upper level */ #else case (int)HWND_NOTOPMOST: #endif XLowerWindow(Disp->display, win); break; default: /* this means a real hWndInsertAfter */ win_restack[0] = WinAfter; win_restack[1] = win; XRestackWindows(Disp->display, win_restack, 2); break; } return 1L; }
void swapLayer(int num1,int num2){ int i; Window windows[MAX_LAYER]; for(i=0;i<layer_num;i++){ if(stack[i]==num1){ stack[i]=num2; }else if(stack[i]==num2){ stack[i]=num1; } } for(i=0;i<layer_num;i++){ windows[i]=layer[stack[i]].win; } XRestackWindows(dis, windows, layer_num); //remapCanvas(); remapLayerMenu(); }
void WindowManager::restack_windows(void) { TRACE_FUNCTION("void WindowManager::restack_windows(void)"); Window* stack = new Window[aot_list.size() + stack_list.size()]; FrameList::iterator it = aot_list.begin(); FrameList::iterator last = aot_list.end(); unsigned int i = 0; for(; it != last && i < aot_list.size(); ++it, i++) stack[i] = fl_xid(*it); it = stack_list.begin(); last = stack_list.end(); for(; it != last && i < aot_list.size() + stack_list.size(); ++it, i++) stack[i] = fl_xid(*it); XRestackWindows(fl_display, stack, stack_list.size()); delete [] stack; }
void appIconMouseDown(WObjDescriptor *desc, XEvent *event) { WAppIcon *aicon = desc->parent; WIcon *icon = aicon->icon; XEvent ev; int x=aicon->x_pos, y=aicon->y_pos; int dx=event->xbutton.x, dy=event->xbutton.y; int grabbed=0; int done=0; int superfluous = wPreferences.superfluous; /* we catch it to avoid problems */ WScreen *scr = icon->core->screen_ptr; WWorkspace *workspace = scr->workspaces[scr->current_workspace]; int shad_x = 0, shad_y = 0, docking=0, dockable, collapsed = 0; int ix, iy; int clickButton = event->xbutton.button; Pixmap ghost = None; Window wins[2]; Bool movingSingle = False; int oldX = x; int oldY = y; Bool hasMoved = False; if (aicon->editing || WCHECK_STATE(WSTATE_MODAL)) return; if (IsDoubleClick(scr, event)) { iconDblClick(desc, event); return; } if (event->xbutton.button == Button3) { WObjDescriptor *desc; WApplication *wapp = wApplicationOf(aicon->icon->owner->main_window); if (!wapp) return; if (event->xbutton.send_event && XGrabPointer(dpy, aicon->icon->core->window, True, ButtonMotionMask |ButtonReleaseMask|ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime) !=GrabSuccess) { wwarning("pointer grab failed for appicon menu"); return; } openApplicationMenu(wapp, event->xbutton.x_root, event->xbutton.y_root); /* allow drag select of menu */ desc = &scr->icon_menu->menu->descriptor; event->xbutton.send_event = True; (*desc->handle_mousedown)(desc, event); return; } #ifdef DEBUG puts("Moving icon"); #endif if (event->xbutton.state & MOD_MASK) wLowerFrame(icon->core); else wRaiseFrame(icon->core); if (XGrabPointer(dpy, icon->core->window, True, ButtonMotionMask |ButtonReleaseMask|ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime) !=GrabSuccess) { wwarning("pointer grab failed for appicon move"); } if (wPreferences.flags.nodock && wPreferences.flags.noclip) dockable = 0; else dockable = canBeDocked(icon->owner); wins[0] = icon->core->window; wins[1] = scr->dock_shadow; XRestackWindows(dpy, wins, 2); if (superfluous) { if (icon->pixmap!=None) ghost = MakeGhostIcon(scr, icon->pixmap); else ghost = MakeGhostIcon(scr, icon->core->window); XSetWindowBackgroundPixmap(dpy, scr->dock_shadow, ghost); XClearWindow(dpy, scr->dock_shadow); } while (!done) { WMMaskEvent(dpy, PointerMotionMask|ButtonReleaseMask|ButtonPressMask |ButtonMotionMask|ExposureMask, &ev); switch (ev.type) { case Expose: WMHandleEvent(&ev); break; case MotionNotify: hasMoved = True; if (!grabbed) { if (abs(dx-ev.xmotion.x)>=MOVE_THRESHOLD || abs(dy-ev.xmotion.y)>=MOVE_THRESHOLD) { XChangeActivePointerGrab(dpy, ButtonMotionMask |ButtonReleaseMask|ButtonPressMask, wCursor[WCUR_MOVE], CurrentTime); grabbed=1; } else { break; } } x = ev.xmotion.x_root - dx; y = ev.xmotion.y_root - dy; if (movingSingle) { XMoveWindow(dpy, icon->core->window, x, y); } else { wAppIconMove(aicon, x, y); } if (dockable) { if (scr->dock && wDockSnapIcon(scr->dock, aicon, x, y, &ix, &iy, False)) { shad_x = scr->dock->x_pos + ix*wPreferences.icon_size; shad_y = scr->dock->y_pos + iy*wPreferences.icon_size; if (scr->last_dock != scr->dock && collapsed) { scr->last_dock->collapsed = 1; wDockHideIcons(scr->last_dock); collapsed = 0; } if (!collapsed && (collapsed = scr->dock->collapsed)) { scr->dock->collapsed = 0; wDockShowIcons(scr->dock); } if (scr->dock->auto_raise_lower) wDockRaise(scr->dock); scr->last_dock = scr->dock; XMoveWindow(dpy, scr->dock_shadow, shad_x, shad_y); if (!docking) { XMapWindow(dpy, scr->dock_shadow); } docking = 1; } else if (workspace->clip && wDockSnapIcon(workspace->clip, aicon, x, y, &ix, &iy, False)) { shad_x = workspace->clip->x_pos + ix*wPreferences.icon_size; shad_y = workspace->clip->y_pos + iy*wPreferences.icon_size; if (scr->last_dock != workspace->clip && collapsed) { scr->last_dock->collapsed = 1; wDockHideIcons(scr->last_dock); collapsed = 0; } if (!collapsed && (collapsed = workspace->clip->collapsed)) { workspace->clip->collapsed = 0; wDockShowIcons(workspace->clip); } if (workspace->clip->auto_raise_lower) wDockRaise(workspace->clip); scr->last_dock = workspace->clip; XMoveWindow(dpy, scr->dock_shadow, shad_x, shad_y); if (!docking) { XMapWindow(dpy, scr->dock_shadow); } docking = 1; } else if (docking) { XUnmapWindow(dpy, scr->dock_shadow); docking = 0; } } break; case ButtonPress: break; case ButtonRelease: if (ev.xbutton.button != clickButton) break; XUngrabPointer(dpy, CurrentTime); if (docking) { Bool docked; /* icon is trying to be docked */ SlideWindow(icon->core->window, x, y, shad_x, shad_y); XUnmapWindow(dpy, scr->dock_shadow); docked = wDockAttachIcon(scr->last_dock, aicon, ix, iy); if (scr->last_dock->auto_collapse) { collapsed = 0; } if (workspace->clip && workspace->clip != scr->last_dock && workspace->clip->auto_raise_lower) wDockLower(workspace->clip); if (!docked) { /* If icon could not be docked, slide it back to the old * position */ SlideWindow(icon->core->window, x, y, oldX, oldY); } wSoundPlay(WSOUND_DOCK); } else { if (movingSingle) { /* move back to its place */ SlideWindow(icon->core->window, x, y, oldX, oldY); wAppIconMove(aicon, oldX, oldY); } else { XMoveWindow(dpy, icon->core->window, x, y); aicon->x_pos = x; aicon->y_pos = y; } if (workspace->clip && workspace->clip->auto_raise_lower) wDockLower(workspace->clip); } if (collapsed) { scr->last_dock->collapsed = 1; wDockHideIcons(scr->last_dock); collapsed = 0; } if (superfluous) { if (ghost!=None) XFreePixmap(dpy, ghost); XSetWindowBackground(dpy, scr->dock_shadow, scr->white_pixel); } if (wPreferences.auto_arrange_icons) wArrangeIcons(scr, True); if (wPreferences.single_click && !hasMoved) iconDblClick(desc, event); done = 1; break; } } #ifdef DEBUG puts("End icon move"); #endif }
/* * Order the windows on the X server to be the same as in our structure. * We do this using XRestackWindows if we don't know the previous order, * or XConfigureWindow on a few particular windows if we do and can figure * out the minimum set of changes. After that, we set __NET_CLIENT_LIST * and __NET_CLIENT_LIST_STACKING. * * FIXME: Now that we have a good view of the stacking order on the server * with MetaStackTracker it should be possible to do a simpler and better * job of computing the minimal set of stacking requests needed. */ static void stack_sync_to_server (MetaStack *stack) { GArray *stacked; GArray *root_children_stacked; GList *tmp; GArray *all_hidden; int n_override_redirect = 0; int n_unmanaging = 0; /* Bail out if frozen */ if (stack->freeze_count > 0) return; meta_topic (META_DEBUG_STACK, "Syncing window stack to server\n"); stack_ensure_sorted (stack); /* Create stacked xwindow arrays. * Painfully, "stacked" is in bottom-to-top order for the * _NET hints, and "root_children_stacked" is in top-to-bottom * order for XRestackWindows() */ stacked = g_array_new (FALSE, FALSE, sizeof (Window)); root_children_stacked = g_array_new (FALSE, FALSE, sizeof (Window)); all_hidden = g_array_new (FALSE, FALSE, sizeof (Window)); /* The screen guard window sits above all hidden windows and acts as * a barrier to input reaching these windows. */ g_array_append_val (all_hidden, stack->screen->guard_window); meta_topic (META_DEBUG_STACK, "Top to bottom: "); meta_push_no_msg_prefix (); for (tmp = stack->sorted; tmp != NULL; tmp = tmp->next) { MetaWindow *w = tmp->data; Window top_level_window; if (w->unmanaging) { n_unmanaging ++; continue; } meta_topic (META_DEBUG_STACK, "%u:%d - %s ", w->layer, w->stack_position, w->desc); /* remember, stacked is in reverse order (bottom to top) */ if (w->override_redirect) n_override_redirect++; else g_array_prepend_val (stacked, w->xwindow); if (w->frame) top_level_window = w->frame->xwindow; else top_level_window = w->xwindow; /* We don't restack hidden windows along with the rest, though they are * reflected in the _NET hints. Hidden windows all get pushed below * the screens fullscreen guard_window. */ if (w->hidden) { g_array_append_val (all_hidden, top_level_window); continue; } /* build XRestackWindows() array from top to bottom */ g_array_append_val (root_children_stacked, top_level_window); } meta_topic (META_DEBUG_STACK, "\n"); meta_pop_no_msg_prefix (); /* All windows should be in some stacking order */ if (stacked->len != stack->windows->len - n_override_redirect - n_unmanaging) meta_bug ("%u windows stacked, %u windows exist in stack\n", stacked->len, stack->windows->len); /* Sync to server */ meta_topic (META_DEBUG_STACK, "Restacking %u windows\n", root_children_stacked->len); meta_error_trap_push (stack->screen->display); if (stack->last_root_children_stacked == NULL) { /* Just impose our stack, we don't know the previous state. * This involves a ton of circulate requests and may flicker. */ meta_topic (META_DEBUG_STACK, "Don't know last stack state, restacking everything\n"); if (root_children_stacked->len > 0) { meta_stack_tracker_record_restack_windows (stack->screen->stack_tracker, (Window *) root_children_stacked->data, root_children_stacked->len, XNextRequest (stack->screen->display->xdisplay)); XRestackWindows (stack->screen->display->xdisplay, (Window *) root_children_stacked->data, root_children_stacked->len); } } else if (root_children_stacked->len > 0) { /* Try to do minimal window moves to get the stack in order */ /* A point of note: these arrays include frames not client windows, * so if a client window has changed frame since last_root_children_stacked * was saved, then we may have inefficiency, but I don't think things * break... */ const Window *old_stack = (Window *) stack->last_root_children_stacked->data; const Window *new_stack = (Window *) root_children_stacked->data; const int old_len = stack->last_root_children_stacked->len; const int new_len = root_children_stacked->len; const Window *oldp = old_stack; const Window *newp = new_stack; const Window *old_end = old_stack + old_len; const Window *new_end = new_stack + new_len; Window last_window = None; while (oldp != old_end && newp != new_end) { if (*oldp == *newp) { /* Stacks are the same here, move on */ ++oldp; last_window = *newp; ++newp; } else if (meta_display_lookup_x_window (stack->screen->display, *oldp) == NULL) { /* *oldp is no longer known to us (probably destroyed), * so we can just skip it */ ++oldp; } else { /* Move *newp below last_window */ if (last_window == None) { meta_topic (META_DEBUG_STACK, "Using window 0x%lx as topmost (but leaving it in-place)\n", *newp); raise_window_relative_to_managed_windows (stack->screen, *newp); } else { /* This means that if last_window is dead, but not * *newp, then we fail to restack *newp; but on * unmanaging last_window, we'll fix it up. */ XWindowChanges changes; changes.sibling = last_window; changes.stack_mode = Below; meta_topic (META_DEBUG_STACK, "Placing window 0x%lx below 0x%lx\n", *newp, last_window); meta_stack_tracker_record_lower_below (stack->screen->stack_tracker, *newp, last_window, XNextRequest (stack->screen->display->xdisplay)); XConfigureWindow (stack->screen->display->xdisplay, *newp, CWSibling | CWStackMode, &changes); } last_window = *newp; ++newp; } } if (newp != new_end) { /* Restack remaining windows */ meta_topic (META_DEBUG_STACK, "Restacking remaining %d windows\n", (int) (new_end - newp)); /* We need to include an already-stacked window * in the restack call, so we get in the proper position * with respect to it. */ if (newp != new_stack) --newp; meta_stack_tracker_record_restack_windows (stack->screen->stack_tracker, (Window *) newp, new_end - newp, XNextRequest (stack->screen->display->xdisplay)); XRestackWindows (stack->screen->display->xdisplay, (Window *) newp, new_end - newp); } } /* Push hidden windows to the bottom of the stack under the guard window */ meta_stack_tracker_record_lower (stack->screen->stack_tracker, stack->screen->guard_window, XNextRequest (stack->screen->display->xdisplay)); XLowerWindow (stack->screen->display->xdisplay, stack->screen->guard_window); meta_stack_tracker_record_restack_windows (stack->screen->stack_tracker, (Window *)all_hidden->data, all_hidden->len, XNextRequest (stack->screen->display->xdisplay)); XRestackWindows (stack->screen->display->xdisplay, (Window *)all_hidden->data, all_hidden->len); g_array_free (all_hidden, TRUE); meta_error_trap_pop (stack->screen->display); /* on error, a window was destroyed; it should eventually * get removed from the stacking list when we unmanage it * and we'll fix stacking at that time. */ /* Sync _NET_CLIENT_LIST and _NET_CLIENT_LIST_STACKING */ XChangeProperty (stack->screen->display->xdisplay, stack->screen->xroot, stack->screen->display->atom__NET_CLIENT_LIST, XA_WINDOW, 32, PropModeReplace, (unsigned char *)stack->windows->data, stack->windows->len); XChangeProperty (stack->screen->display->xdisplay, stack->screen->xroot, stack->screen->display->atom__NET_CLIENT_LIST_STACKING, XA_WINDOW, 32, PropModeReplace, (unsigned char *)stacked->data, stacked->len); g_array_free (stacked, TRUE); if (stack->last_root_children_stacked) g_array_free (stack->last_root_children_stacked, TRUE); stack->last_root_children_stacked = root_children_stacked; /* That was scary... */ }
void EXRestackWindows(Window * windows, int nwindows) { XRestackWindows(disp, windows, nwindows); }
Bool wHandleAppIconMove(WAppIcon *aicon, XEvent *event) { WIcon *icon = aicon->icon; virtual_screen *vscr = aicon->icon->vscr; WScreen *scr = vscr->screen_ptr; WDock *originalDock = aicon->dock; /* can be NULL */ WDock *lastDock = originalDock; WDock *allDocks[vscr->drawer.drawer_count + 2]; /* clip, dock and drawers (order determined at runtime) */ WDrawerChain *dc; Bool dockable = True; Bool ondock = True; Bool grabbed = False; Bool collapsed = False; /* Stores the collapsed state of lastDock, before the moving appicon entered it */ int superfluous = wPreferences.superfluous; /* we cache it to avoid problems */ int omnipresent = aicon->omnipresent; /* this must be cached */ Bool showed_all_clips = False; int clickButton = event->xbutton.button; Pixmap ghost = None; Window wins[2]; /* Managing shadow window */ XEvent ev; int x = aicon->x_pos, y = aicon->y_pos; int ofs_x = event->xbutton.x, ofs_y = event->xbutton.y; int shad_x = x, shad_y = y; int ix = aicon->xindex, iy = aicon->yindex; int i; int oldX = x; int oldY = y; Bool hasMoved = False; if (wPreferences.flags.noupdates && originalDock != NULL) return False; if (event->xbutton.state & MOD_MASK) { /* * If Mod is pressed for an docked appicon, * assume it is to undock it,so don't lower it */ if (originalDock == NULL) wLowerFrame(icon->vscr, icon->core); } else { wRaiseFrame(icon->vscr, icon->core); } if (XGrabPointer(dpy, icon->core->window, True, ButtonMotionMask | ButtonReleaseMask | ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime) != GrabSuccess) wwarning("Pointer grab failed in wHandleAppIconMove"); if (originalDock == NULL) { ondock = False; if (wPreferences.flags.nodock && wPreferences.flags.noclip && wPreferences.flags.nodrawer) dockable = False; else dockable = canBeDocked(icon->owner); } /* * We try the various docks in that order: * - First, the dock the appicon comes from, if any * - Then, the drawers * - Then, the "dock" (WM_DOCK) * - Finally, the clip */ i = 0; if (originalDock != NULL) allDocks[i++] = originalDock; /* Testing vscr->drawers is enough, no need to test wPreferences.flags.nodrawer */ for (dc = vscr->drawer.drawers; dc != NULL; dc = dc->next) if (dc->adrawer != originalDock) allDocks[i++] = dc->adrawer; if (!wPreferences.flags.nodock && vscr->dock.dock != originalDock) allDocks[i++] = vscr->dock.dock; if (!wPreferences.flags.noclip && originalDock != vscr->workspace.array[vscr->workspace.current]->clip) allDocks[i++] = vscr->workspace.array[vscr->workspace.current]->clip; /* In case the clip, the dock, or both, are disabled */ for ( ; i < vscr->drawer.drawer_count + 2; i++) allDocks[i] = NULL; wins[0] = icon->core->window; wins[1] = scr->dock_shadow; XRestackWindows(dpy, wins, 2); XMoveResizeWindow(dpy, scr->dock_shadow, aicon->x_pos, aicon->y_pos, ICON_SIZE, ICON_SIZE); if (superfluous) { if (icon->pixmap != None) ghost = MakeGhostIcon(vscr, icon->pixmap); else ghost = MakeGhostIcon(vscr, icon->core->window); XSetWindowBackgroundPixmap(dpy, scr->dock_shadow, ghost); XClearWindow(dpy, scr->dock_shadow); } if (ondock) XMapWindow(dpy, scr->dock_shadow); while (1) { WMMaskEvent(dpy, PointerMotionMask | ButtonReleaseMask | ButtonPressMask | ButtonMotionMask | ExposureMask | EnterWindowMask, &ev); switch (ev.type) { case Expose: WMHandleEvent(&ev); break; case EnterNotify: /* * It means the cursor moved so fast that it entered * something else (if moving slowly, it would have * stayed in the appIcon that is being moved. Ignore * such "spurious" EnterNotifiy's */ break; case MotionNotify: hasMoved = True; appicon_move_motion(vscr, scr, ev, &lastDock, &originalDock, aicon, allDocks, &collapsed, &dockable, &ondock, &x, &y, &ix, &iy, &shad_x, &shad_y, &ofs_x, &ofs_y, &grabbed, omnipresent, &showed_all_clips); break; case ButtonPress: break; case ButtonRelease: if (ev.xbutton.button != clickButton) break; appicon_move_button_release(originalDock, lastDock, aicon, icon, x, y, oldX, oldY, shad_x, shad_y, ix, iy, &collapsed, ondock, ghost, showed_all_clips); return hasMoved; } } }