~ctwm/ctwm/trunk

« back to all changes in this revision

Viewing changes to functions_misc.c

  • Committer: Matthew Fuller
  • Date: 2016-09-11 15:41:36 UTC
  • mto: This revision was merged to the branch mainline in revision 522.
  • Revision ID: fullermd@over-yonder.net-20160911154136-mrh2qth2nh2pxcqq
tracefile is used broadly across the code for debug output.  Move it
to util.[ch]; it's maybe a little wrong there, but it's _very_ wrong
having it as part of the event code.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Misc function implementation
3
 
 *
4
 
 * These are things that either don't fit neatly into another category,
5
 
 * or fit into a category too small to be worth making individual files
6
 
 * for.
7
 
 */
8
 
 
9
 
#include "ctwm.h"
10
 
 
11
 
#include <stdlib.h>
12
 
 
13
 
#include "animate.h"
14
 
#include "functions.h"
15
 
#include "functions_defs.h"
16
 
#include "functions_internal.h"
17
 
#include "icons.h"
18
 
#include "menus.h"
19
 
#include "otp.h"
20
 
#include "screen.h"
21
 
#ifdef SOUNDS
22
 
#include "sound.h"
23
 
#endif
24
 
#include "util.h"
25
 
#include "win_iconify.h"
26
 
#include "windowbox.h"
27
 
#include "workspace_utils.h"
28
 
 
29
 
#include "ext/repl_str.h"
30
 
 
31
 
 
32
 
 
33
 
/*
34
 
 * Animation-related
35
 
 */
36
 
DFHANDLER(startanimation)
37
 
{
38
 
        StartAnimation();
39
 
}
40
 
 
41
 
DFHANDLER(stopanimation)
42
 
{
43
 
        StopAnimation();
44
 
}
45
 
 
46
 
DFHANDLER(speedupanimation)
47
 
{
48
 
        ModifyAnimationSpeed(1);
49
 
}
50
 
 
51
 
DFHANDLER(slowdownanimation)
52
 
{
53
 
        ModifyAnimationSpeed(-1);
54
 
}
55
 
 
56
 
 
57
 
 
58
 
/*
59
 
 * Menu-related
60
 
 */
61
 
DFHANDLER(menu)
62
 
{
63
 
        if(action && ! strncmp(action, "WGOTO : ", 8)) {
64
 
                GotoWorkSpaceByName(/* XXXXX */ Scr->currentvs,
65
 
                                                ((char *)action) + 8);
66
 
        }
67
 
        else {
68
 
                MenuItem *item;
69
 
 
70
 
                item = ActiveItem;
71
 
                while(item && item->sub) {
72
 
                        if(!item->sub->defaultitem) {
73
 
                                break;
74
 
                        }
75
 
                        if(item->sub->defaultitem->func != F_MENU) {
76
 
                                break;
77
 
                        }
78
 
                        item = item->sub->defaultitem;
79
 
                }
80
 
                if(item && item->sub && item->sub->defaultitem) {
81
 
                        ExecuteFunction(item->sub->defaultitem->func,
82
 
                                        item->sub->defaultitem->action,
83
 
                                        w, tmp_win, eventp, context, pulldown);
84
 
                }
85
 
        }
86
 
}
87
 
 
88
 
 
89
 
DFHANDLER(pin)
90
 
{
91
 
        if(! ActiveMenu) {
92
 
                return;
93
 
        }
94
 
        if(ActiveMenu->pinned) {
95
 
                XUnmapWindow(dpy, ActiveMenu->w);
96
 
                ActiveMenu->mapped = MRM_UNMAPPED;
97
 
        }
98
 
        else {
99
 
                XWindowAttributes attr;
100
 
                MenuRoot *menu;
101
 
 
102
 
                if(ActiveMenu->pmenu == NULL) {
103
 
                        menu  = malloc(sizeof(MenuRoot));
104
 
                        *menu = *ActiveMenu;
105
 
                        menu->pinned = true;
106
 
                        menu->mapped = MRM_NEVER;
107
 
                        menu->width -= 10;
108
 
                        if(menu->pull) {
109
 
                                menu->width -= 16 + 10;
110
 
                        }
111
 
                        MakeMenu(menu);
112
 
                        ActiveMenu->pmenu = menu;
113
 
                }
114
 
                else {
115
 
                        menu = ActiveMenu->pmenu;
116
 
                }
117
 
                if(menu->mapped == MRM_MAPPED) {
118
 
                        return;
119
 
                }
120
 
                XGetWindowAttributes(dpy, ActiveMenu->w, &attr);
121
 
                menu->x = attr.x;
122
 
                menu->y = attr.y;
123
 
                XMoveWindow(dpy, menu->w, menu->x, menu->y);
124
 
                XMapRaised(dpy, menu->w);
125
 
                menu->mapped = MRM_MAPPED;
126
 
        }
127
 
        PopDownMenu();
128
 
}
129
 
 
130
 
 
131
 
 
132
 
/*
133
 
 * Alternate keymaps/contexts
134
 
 */
135
 
DFHANDLER(altkeymap)
136
 
{
137
 
        int alt, stat_;
138
 
 
139
 
        if(! action) {
140
 
                return;
141
 
        }
142
 
        stat_ = sscanf(action, "%d", &alt);
143
 
        if(stat_ != 1) {
144
 
                return;
145
 
        }
146
 
        if((alt < 1) || (alt > 5)) {
147
 
                return;
148
 
        }
149
 
        AlternateKeymap = Alt1Mask << (alt - 1);
150
 
        XGrabPointer(dpy, Scr->Root, True, ButtonPressMask | ButtonReleaseMask,
151
 
                     GrabModeAsync, GrabModeAsync,
152
 
                     Scr->Root, Scr->AlterCursor, CurrentTime);
153
 
        func_reset_cursor = false;  // Leave special cursor alone
154
 
        XGrabKeyboard(dpy, Scr->Root, True, GrabModeAsync, GrabModeAsync, CurrentTime);
155
 
        return;
156
 
}
157
 
 
158
 
DFHANDLER(altcontext)
159
 
{
160
 
        AlternateContext = true;
161
 
        XGrabPointer(dpy, Scr->Root, False, ButtonPressMask | ButtonReleaseMask,
162
 
                     GrabModeAsync, GrabModeAsync,
163
 
                     Scr->Root, Scr->AlterCursor, CurrentTime);
164
 
        func_reset_cursor = false;  // Leave special cursor alone
165
 
        XGrabKeyboard(dpy, Scr->Root, False, GrabModeAsync, GrabModeAsync, CurrentTime);
166
 
        return;
167
 
}
168
 
 
169
 
 
170
 
 
171
 
/*
172
 
 * A few trivial ctwm-control-ish meta-functions
173
 
 */
174
 
DFHANDLER(quit)
175
 
{
176
 
        Done(0);
177
 
}
178
 
 
179
 
DFHANDLER(restart)
180
 
{
181
 
        DoRestart(eventp->xbutton.time);
182
 
}
183
 
 
184
 
DFHANDLER(beep)
185
 
{
186
 
        XBell(dpy, 0);
187
 
}
188
 
 
189
 
DFHANDLER(trace)
190
 
{
191
 
        DebugTrace(action);
192
 
}
193
 
 
194
 
 
195
 
 
196
 
/*
197
 
 * Special windowbox-related
198
 
 */
199
 
DFHANDLER(fittocontent)
200
 
{
201
 
        if(!tmp_win->iswinbox) {
202
 
                XBell(dpy, 0);
203
 
                return;
204
 
        }
205
 
        fittocontent(tmp_win);
206
 
}
207
 
 
208
 
 
209
 
 
210
 
/*
211
 
 * A few things that are sorta windows/icons related, but don't really
212
 
 * fit with the window-targetted things in functions_win.
213
 
 */
214
 
DFHANDLER(showbackground)
215
 
{
216
 
        ShowBackground(Scr->currentvs, -1);
217
 
}
218
 
 
219
 
DFHANDLER(raiseicons)
220
 
{
221
 
        for(TwmWindow *t = Scr->FirstWindow; t != NULL; t = t->next) {
222
 
                if(t->icon && t->icon->w) {
223
 
                        OtpRaise(t, IconWin);
224
 
                }
225
 
        }
226
 
}
227
 
 
228
 
DFHANDLER(rescuewindows)
229
 
{
230
 
        RescueWindows();
231
 
}
232
 
 
233
 
 
234
 
 
235
 
/*
236
 
 * Despite the name, this is more like 'gotoworkspace' than the other
237
 
 * 'warpto*' funcs, as it's just about switching your view, not anything
238
 
 * going to a window.
239
 
 */
240
 
DFHANDLER(warptoscreen)
241
 
{
242
 
        if(strcmp(action, WARPSCREEN_NEXT) == 0) {
243
 
                WarpToScreen(Scr->screen + 1, 1);
244
 
        }
245
 
        else if(strcmp(action, WARPSCREEN_PREV) == 0) {
246
 
                WarpToScreen(Scr->screen - 1, -1);
247
 
        }
248
 
        else if(strcmp(action, WARPSCREEN_BACK) == 0) {
249
 
                WarpToScreen(PreviousScreen, 0);
250
 
        }
251
 
        else {
252
 
                WarpToScreen(atoi(action), 0);
253
 
        }
254
 
}
255
 
 
256
 
 
257
 
 
258
 
/*
259
 
 * Sound-related
260
 
 */
261
 
#ifdef SOUNDS
262
 
static
263
 
DFHANDLER(togglesound)
264
 
{
265
 
        toggle_sound();
266
 
}
267
 
static
268
 
DFHANDLER(rereadsounds)
269
 
{
270
 
        reread_sounds();
271
 
}
272
 
#endif
273
 
 
274
 
 
275
 
 
276
 
/*
277
 
 * And executing an external program
278
 
 */
279
 
static void Execute(const char *_s);
280
 
 
281
 
DFHANDLER(exec)
282
 
{
283
 
        PopDownMenu();
284
 
        if(!Scr->NoGrabServer) {
285
 
                XUngrabServer(dpy);
286
 
                XSync(dpy, 0);
287
 
        }
288
 
        XUngrabPointer(dpy, CurrentTime);
289
 
        XSync(dpy, 0);
290
 
        Execute(action);
291
 
}
292
 
 
293
 
 
294
 
static void
295
 
Execute(const char *_s)
296
 
{
297
 
        char *s;
298
 
        char *_ds;
299
 
        char *orig_display;
300
 
        int restorevar = 0;
301
 
        char *subs;
302
 
 
303
 
        /* Seatbelt */
304
 
        if(!_s) {
305
 
                return;
306
 
        }
307
 
 
308
 
        /* Work on a local copy since we're mutating it */
309
 
        s = strdup(_s);
310
 
        if(!s) {
311
 
                return;
312
 
        }
313
 
 
314
 
        /* Stash up current $DISPLAY value for resetting */
315
 
        orig_display = getenv("DISPLAY");
316
 
 
317
 
 
318
 
        /*
319
 
         * Build a display string using the current screen number, so that
320
 
         * X programs which get fired up from a menu come up on the screen
321
 
         * that they were invoked from, unless specifically overridden on
322
 
         * their command line.
323
 
         *
324
 
         * Which is to say, given that we're on display "foo.bar:1.2", we
325
 
         * want to translate that into "foo.bar:1.{Scr->screen}".
326
 
         *
327
 
         * We strdup() because DisplayString() is a macro returning into the
328
 
         * dpy structure, and we're going to mutate the value we get from it.
329
 
         */
330
 
        _ds = DisplayString(dpy);
331
 
        if(_ds) {
332
 
                char *ds;
333
 
                char *colon;
334
 
 
335
 
                ds = strdup(_ds);
336
 
                if(!ds) {
337
 
                        goto end_execute;
338
 
                }
339
 
 
340
 
                /* If it's not host:dpy, we don't have anything to do here */
341
 
                colon = strrchr(ds, ':');
342
 
                if(colon) {
343
 
                        char *dot, *new_display;
344
 
 
345
 
                        /* Find the . in display.screen and chop it off */
346
 
                        dot = strchr(colon, '.');
347
 
                        if(dot) {
348
 
                                *dot = '\0';
349
 
                        }
350
 
 
351
 
                        /* Build a new string with our correct screen info */
352
 
                        asprintf(&new_display, "%s.%d", ds, Scr->screen);
353
 
                        if(!new_display) {
354
 
                                free(ds);
355
 
                                goto end_execute;
356
 
                        }
357
 
 
358
 
                        /* And set */
359
 
                        setenv("DISPLAY", new_display, 1);
360
 
                        free(new_display);
361
 
                        restorevar = 1;
362
 
                }
363
 
                free(ds);
364
 
        }
365
 
 
366
 
 
367
 
        /*
368
 
         * We replace a couple placeholders in the string.  $currentworkspace
369
 
         * is documented in the manual; $redirect is not.
370
 
         */
371
 
        subs = strstr(s, "$currentworkspace");
372
 
        if(subs) {
373
 
                char *tmp;
374
 
                char *wsname;
375
 
 
376
 
                wsname = GetCurrentWorkSpaceName(Scr->currentvs);
377
 
                if(!wsname) {
378
 
                        wsname = "";
379
 
                }
380
 
 
381
 
                tmp = replace_substr(s, "$currentworkspace", wsname);
382
 
                if(!tmp) {
383
 
                        goto end_execute;
384
 
                }
385
 
                free(s);
386
 
                s = tmp;
387
 
        }
388
 
 
389
 
        subs = strstr(s, "$redirect");
390
 
        if(subs) {
391
 
                char *tmp;
392
 
                char *redir;
393
 
 
394
 
                if(CLarg.is_captive) {
395
 
                        asprintf(&redir, "-xrm 'ctwm.redirect:%s'", Scr->captivename);
396
 
                        if(!redir) {
397
 
                                goto end_execute;
398
 
                        }
399
 
                }
400
 
                else {
401
 
                        redir = malloc(1);
402
 
                        *redir = '\0';
403
 
                }
404
 
 
405
 
                tmp = replace_substr(s, "$redirect", redir);
406
 
                free(s);
407
 
                s = tmp;
408
 
 
409
 
                free(redir);
410
 
        }
411
 
 
412
 
 
413
 
        /*
414
 
         * Call it.  Return value doesn't really matter, since whatever
415
 
         * happened we're done.  Maybe someday if we develop a "show user
416
 
         * message" generalized func, we can tell the user if executing
417
 
         * failed somehow.
418
 
         */
419
 
        system(s);
420
 
 
421
 
 
422
 
        /*
423
 
         * Restore $DISPLAY if we changed it.  It's probably only necessary
424
 
         * in edge cases (it might be used by ctwm restarting itself, for
425
 
         * instance) and it's not quite clear whether the DisplayString()
426
 
         * result would even be wrong for that, but what the heck, setenv()
427
 
         * is cheap.
428
 
         */
429
 
        if(restorevar) {
430
 
                if(orig_display) {
431
 
                        setenv("DISPLAY", orig_display, 1);
432
 
                }
433
 
                else {
434
 
                        unsetenv("DISPLAY");
435
 
                }
436
 
        }
437
 
 
438
 
 
439
 
        /* Clean up */
440
 
end_execute:
441
 
        free(s);
442
 
        return;
443
 
}