functions_warp.c revision 0bbfda8a
1/* 2 * Functions related to the warp ring 3 * 4 * There are functions that are _named_ like warp-ring funcs, but aren't 5 * really, and so aren't here. Some examples are f.warphere which is 6 * workspaces-related, and f.warptoscreen which is screen-related. 7 * 8 * There are also funcs that aren't really ring related, but I've put 9 * here because they're still warping to window related, like f.warpto / 10 * f.warptoiconmgr. 11 */ 12 13#include "ctwm.h" 14 15#include <string.h> 16 17#include "functions_internal.h" 18#include "iconmgr.h" 19#include "list.h" 20#include "otp.h" 21#include "screen.h" 22#include "win_iconify.h" 23#include "win_utils.h" 24 25 26static void WarpAlongRing(XButtonEvent *ev, bool forward); 27 28 29DFHANDLER(warpto) 30{ 31 TwmWindow *tw; 32 int len; 33 34 len = strlen(action); 35 36#ifdef WARPTO_FROM_ICONMGR 37 /* XXX should be iconmgrp? */ 38 if(len == 0 && tmp_win && tmp_win->iconmgr) { 39 printf("curren iconmgr entry: %s", tmp_win->iconmgr->Current); 40 } 41#endif /* #ifdef WARPTO_FROM_ICONMGR */ 42 for(tw = Scr->FirstWindow; tw != NULL; tw = tw->next) { 43 if(!strncmp(action, tw->name, len)) { 44 break; 45 } 46 if(match(action, tw->name)) { 47 break; 48 } 49 } 50 if(!tw) { 51 for(tw = Scr->FirstWindow; tw != NULL; tw = tw->next) { 52 if(!strncmp(action, tw->class.res_name, len)) { 53 break; 54 } 55 if(match(action, tw->class.res_name)) { 56 break; 57 } 58 } 59 if(!tw) { 60 for(tw = Scr->FirstWindow; tw != NULL; tw = tw->next) { 61 if(!strncmp(action, tw->class.res_class, len)) { 62 break; 63 } 64 if(match(action, tw->class.res_class)) { 65 break; 66 } 67 } 68 } 69 } 70 71 if(tw) { 72 if(Scr->WarpUnmapped || tw->mapped) { 73 if(!tw->mapped) { 74 DeIconify(tw); 75 } 76 WarpToWindow(tw, Scr->RaiseOnWarp); 77 } 78 } 79 else { 80 XBell(dpy, 0); 81 } 82} 83 84 85DFHANDLER(warptoiconmgr) 86{ 87 TwmWindow *tw, *raisewin = NULL; 88 int len; 89 Window iconwin = None; 90 91 len = strlen(action); 92 if(len == 0) { 93 if(tmp_win && tmp_win->iconmanagerlist) { 94 raisewin = tmp_win->iconmanagerlist->iconmgr->twm_win; 95 iconwin = tmp_win->iconmanagerlist->icon; 96 } 97 else if(Scr->iconmgr->active) { 98 raisewin = Scr->iconmgr->twm_win; 99 iconwin = Scr->iconmgr->active->w; 100 } 101 } 102 else { 103 for(tw = Scr->FirstWindow; tw != NULL; tw = tw->next) { 104 if(strncmp(action, tw->icon_name, len) == 0) { 105 if(tw->iconmanagerlist && 106 tw->iconmanagerlist->iconmgr->twm_win->mapped) { 107 raisewin = tw->iconmanagerlist->iconmgr->twm_win; 108 break; 109 } 110 } 111 } 112 } 113 114 if(raisewin) { 115 OtpRaise(raisewin, WinWin); 116 XWarpPointer(dpy, None, iconwin, 0, 0, 0, 0, 5, 5); 117 } 118 else { 119 XBell(dpy, 0); 120 } 121} 122 123 124/* Taken from vtwm version 5.3 */ 125DFHANDLER(ring) 126{ 127 if(tmp_win->ring.next || tmp_win->ring.prev) { 128 /* It's in the ring, let's take it out. */ 129 TwmWindow *prev = tmp_win->ring.prev, *next = tmp_win->ring.next; 130 131 /* 132 * 1. Unlink window 133 * 2. If window was only thing in ring, null out ring 134 * 3. If window was ring leader, set to next (or null) 135 */ 136 if(prev) { 137 prev->ring.next = next; 138 } 139 if(next) { 140 next->ring.prev = prev; 141 } 142 if(Scr->Ring == tmp_win) { 143 Scr->Ring = (next != tmp_win ? next : NULL); 144 } 145 146 if(!Scr->Ring || Scr->RingLeader == tmp_win) { 147 Scr->RingLeader = Scr->Ring; 148 } 149 tmp_win->ring.next = tmp_win->ring.prev = NULL; 150 } 151 else { 152 /* Not in the ring, so put it in. */ 153 if(Scr->Ring) { 154 tmp_win->ring.next = Scr->Ring->ring.next; 155 if(Scr->Ring->ring.next->ring.prev) { 156 Scr->Ring->ring.next->ring.prev = tmp_win; 157 } 158 Scr->Ring->ring.next = tmp_win; 159 tmp_win->ring.prev = Scr->Ring; 160 } 161 else { 162 tmp_win->ring.next = tmp_win->ring.prev = Scr->Ring = tmp_win; 163 } 164 } 165 /*tmp_win->ring.cursor_valid = false;*/ 166} 167 168 169DFHANDLER(warpring) 170{ 171 switch(((char *)action)[0]) { 172 case 'n': 173 WarpAlongRing(&eventp->xbutton, true); 174 break; 175 case 'p': 176 WarpAlongRing(&eventp->xbutton, false); 177 break; 178 default: 179 XBell(dpy, 0); 180 break; 181 } 182} 183 184 185/* 186 * Synthetic function: this is used internally as the action in some 187 * magic menus like the TwmWindows et al. 188 */ 189DFHANDLER(winwarp) 190{ 191 tmp_win = (TwmWindow *)action; 192 193 if(! tmp_win) { 194 return; 195 } 196 if(Scr->WarpUnmapped || tmp_win->mapped) { 197 if(!tmp_win->mapped) { 198 DeIconify(tmp_win); 199 } 200 WarpToWindow(tmp_win, Scr->RaiseOnWarp); 201 } 202} 203 204 205/* 206 * Backend util for f.warpring 207 */ 208static void 209WarpAlongRing(XButtonEvent *ev, bool forward) 210{ 211 TwmWindow *r, *head; 212 213 if(Scr->RingLeader) { 214 head = Scr->RingLeader; 215 } 216 else if(!(head = Scr->Ring)) { 217 return; 218 } 219 220 if(forward) { 221 for(r = head->ring.next; r != head; r = r->ring.next) { 222 if(!r) { 223 break; 224 } 225 if(r->mapped && (Scr->WarpRingAnyWhere || visible(r))) { 226 break; 227 } 228 } 229 } 230 else { 231 for(r = head->ring.prev; r != head; r = r->ring.prev) { 232 if(!r) { 233 break; 234 } 235 if(r->mapped && (Scr->WarpRingAnyWhere || visible(r))) { 236 break; 237 } 238 } 239 } 240 241 /* Note: (Scr->Focus != r) is necessary when we move to a workspace that 242 has a single window and we want warping to warp to it. */ 243 if(r && (r != head || Scr->Focus != r)) { 244 TwmWindow *p = Scr->RingLeader, *t; 245 246 Scr->RingLeader = r; 247 WarpToWindow(r, true); 248 249 if(p && p->mapped && 250 (t = GetTwmWindow(ev->window)) && 251 p == t) { 252 p->ring.cursor_valid = true; 253 p->ring.curs_x = ev->x_root - t->frame_x; 254 p->ring.curs_y = ev->y_root - t->frame_y; 255#ifdef DEBUG 256 /* XXX This is the Tmp_win [now] internal to the event code? */ 257 fprintf(stderr, 258 "WarpAlongRing: cursor_valid := true; x := %d (%d-%d), y := %d (%d-%d)\n", 259 Tmp_win->ring.curs_x, ev->x_root, t->frame_x, Tmp_win->ring.curs_y, ev->y_root, 260 t->frame_y); 261#endif 262 /* 263 * The check if the cursor position is inside the window is now 264 * done in WarpToWindow(). 265 */ 266 } 267 } 268} 269