6
#include "connections.h"
9
char *guess_desktop(void);
10
void solid_bg(int restore);
13
static void usr_bin_path(int restore);
14
static int dt_cmd(char *cmd);
15
static char *cmd_output(char *cmd);
16
XImage *solid_root(char *color);
17
static void solid_cde(char *color);
18
static void solid_gnome(char *color);
19
static void solid_kde(char *color);
22
static void usr_bin_path(int restore) {
23
static char *oldpath = NULL;
25
char addpath[] = "/usr/bin:/bin:";
29
set_env("PATH", oldpath);
37
oldpath = strdup(getenv("PATH"));
39
oldpath = strdup("/usr/bin");
41
newpath = (char *) malloc(strlen(oldpath) + strlen(addpath) + 1);
43
strcat(newpath, addpath);
44
strcat(newpath, oldpath);
45
set_env("PATH", newpath);
49
static int dt_cmd(char *cmd) {
54
if (!cmd || *cmd == '\0') {
59
if (no_external_cmds || !cmd_ok("dt")) {
60
rfbLog("cannot run external commands in -nocmds mode:\n");
61
rfbLog(" \"%s\"\n", cmd);
62
rfbLog(" dt_cmd: returning 1\n");
66
if (getenv("DISPLAY") == NULL) {
67
set_env("DISPLAY", DisplayString(dpy));
70
rfbLog("running command:\n");
72
fprintf(stderr, "\n %s\n\n", cmd);
85
static char *cmd_output(char *cmd) {
87
static char output[50000];
91
if (!cmd || *cmd == '\0') {
95
if (no_external_cmds) {
96
rfbLog("cannot run external commands in -nocmds mode:\n");
97
rfbLog(" \"%s\"\n", cmd);
98
rfbLog(" cmd_output: null string.\n");
102
rfbLog("running pipe:\n");
104
fprintf(stderr, "\n %s\n\n", cmd);
113
while (fgets(line, 1024, p) != NULL) {
114
if (strlen(output) + strlen(line) + 1 < 50000) {
115
strcat(output, line);
122
static char *last_color = NULL;
124
unsigned long get_pixel(char *color) {
130
unsigned long pixel = BlackPixel(dpy, scr);
131
if (depth > 8 || strcmp(color, solid_default)) {
132
cmap = DefaultColormap (dpy, scr);
133
if (XParseColor(dpy, cmap, color, &cdef) &&
134
XAllocColor(dpy, cmap, &cdef)) {
137
rfbLog("error parsing/allocing color: %s\n", color);
144
XImage *solid_root(char *color) {
151
static XImage *image = NULL;
155
XSetWindowAttributes swa;
157
static unsigned long mask, pixel = 0;
161
if (subwin || window != rootwin) {
162
rfbLog("cannot set subwin to solid color, must be rootwin\n");
166
/* create the "clear" window just for generating exposures */
167
swa.override_redirect = True;
168
swa.backing_store = NotUseful;
169
swa.save_under = False;
170
swa.background_pixmap = None;
171
visual.visualid = CopyFromParent;
172
mask = (CWOverrideRedirect|CWBackingStore|CWSaveUnder|CWBackPixmap);
173
expose = XCreateWindow(dpy, window, 0, 0, wdpy_x, wdpy_y, 0, depth,
174
InputOutput, &visual, mask, &swa);
180
XDestroyWindow(dpy, expose);
181
rfbLog("no root snapshot available.\n");
185
/* restore the root window from the XImage snapshot */
186
pixmap = XCreatePixmap(dpy, window, wdpy_x, wdpy_y, depth);
188
/* draw the image to a pixmap: */
189
gcv.function = GXcopy;
190
gcv.plane_mask = AllPlanes;
191
gc = XCreateGC(dpy, window, GCFunction|GCPlaneMask, &gcv);
193
XPutImage(dpy, pixmap, gc, image, 0, 0, 0, 0, wdpy_x, wdpy_y);
195
gcv.foreground = gcv.background = BlackPixel(dpy, scr);
196
gc = XCreateGC(dpy, window, GCForeground|GCBackground, &gcv);
198
rfbLog("restoring root snapshot...\n");
199
/* set the pixmap as the bg: */
200
XSetWindowBackgroundPixmap(dpy, window, pixmap);
201
XFreePixmap(dpy, pixmap);
202
XClearWindow(dpy, window);
205
/* generate exposures */
206
XMapWindow(dpy, expose);
208
XDestroyWindow(dpy, expose);
213
/* need to retrieve a snapshot of the root background: */
215
XSetWindowAttributes iswa;
217
/* create image window: */
218
iswa.override_redirect = True;
219
iswa.backing_store = NotUseful;
220
iswa.save_under = False;
221
iswa.background_pixmap = ParentRelative;
223
iwin = XCreateWindow(dpy, window, 0, 0, wdpy_x, wdpy_y, 0,
224
depth, InputOutput, &visual, mask, &iswa);
226
rfbLog("snapshotting background...\n");
228
XMapWindow(dpy, iwin);
230
image = XGetImage(dpy, iwin, 0, 0, wdpy_x, wdpy_y, AllPlanes,
233
XDestroyWindow(dpy, iwin);
236
if (color == (char *) 0x1) {
237
/* caller will XDestroyImage it: */
243
/* use black for low colors or failure */
244
pixel = get_pixel(color);
246
rfbLog("setting solid background...\n");
247
XSetWindowBackground(dpy, window, pixel);
248
XMapWindow(dpy, expose);
250
XDestroyWindow(dpy, expose);
255
static void solid_cde(char *color) {
262
static XImage *image[16];
263
static Window ws_wins[16];
270
XSetWindowAttributes swa;
272
unsigned long mask, pixel;
279
if (subwin || window != rootwin) {
280
rfbLog("cannot set subwin to solid color, must be rootwin\n");
284
/* create the "clear" window just for generating exposures */
285
swa.override_redirect = True;
286
swa.backing_store = NotUseful;
287
swa.save_under = False;
288
swa.background_pixmap = None;
289
visual.visualid = CopyFromParent;
290
mask = (CWOverrideRedirect|CWBackingStore|CWSaveUnder|CWBackPixmap);
291
expose = XCreateWindow(dpy, window, 0, 0, wdpy_x, wdpy_y, 0, depth,
292
InputOutput, &visual, mask, &swa);
295
/* restore the backdrop windows from the XImage snapshots */
297
for (n=0; n < nws; n++) {
308
if (! valid_window(twin, NULL, 0)) {
312
pixmap = XCreatePixmap(dpy, twin, wdpy_x, wdpy_y,
315
/* draw the image to a pixmap: */
316
gcv.function = GXcopy;
317
gcv.plane_mask = AllPlanes;
318
gc = XCreateGC(dpy, twin, GCFunction|GCPlaneMask, &gcv);
320
XPutImage(dpy, pixmap, gc, image[n], 0, 0, 0, 0,
323
gcv.foreground = gcv.background = BlackPixel(dpy, scr);
324
gc = XCreateGC(dpy, twin, GCForeground|GCBackground,
327
rfbLog("restoring CDE ws%d snapshot to 0x%lx\n",
329
/* set the pixmap as the bg: */
330
XSetWindowBackgroundPixmap(dpy, twin, pixmap);
331
XFreePixmap(dpy, pixmap);
332
XClearWindow(dpy, twin);
336
/* generate exposures */
337
XMapWindow(dpy, expose);
339
XDestroyWindow(dpy, expose);
344
/* need to retrieve snapshots of the ws backgrounds: */
346
XSetWindowAttributes iswa;
347
Atom dt_list, wm_info, type;
349
unsigned long length, after;
351
unsigned long *dp; /* crash on 64bit with int */
355
/* extract the hidden wm properties about backdrops: */
357
wm_info = XInternAtom(dpy, "_MOTIF_WM_INFO", True);
358
if (wm_info == None) {
362
XGetWindowProperty(dpy, rootwin, wm_info, 0L, 10L, False,
363
AnyPropertyType, &type, &format, &length, &after, &data);
366
* xprop -notype -root _MOTIF_WM_INFO
367
* _MOTIF_WM_INFO = 0x2, 0x580028
370
if (length < 2 || format != 32 || after != 0) {
374
dp = (unsigned long *) data;
375
wm_win = (Window) *(dp+1); /* 2nd item. */
378
dt_list = XInternAtom(dpy, "_DT_WORKSPACE_LIST", True);
379
if (dt_list == None) {
383
XGetWindowProperty(dpy, wm_win, dt_list, 0L, 10L, False,
384
AnyPropertyType, &type, &format, &length, &after, &data);
395
rfbLog("special CDE win: 0x%lx, %d workspaces\n", wm_win, nws);
400
for (n=0; n<nws; n++) {
404
XWindowAttributes attr;
410
sprintf(tmp, "_DT_WORKSPACE_INFO_ws%d", n);
411
ws_atom = XInternAtom(dpy, tmp, False);
412
if (ws_atom == None) {
415
XGetWindowProperty(dpy, wm_win, ws_atom, 0L, 100L,
416
False, AnyPropertyType, &type, &format, &length,
419
if (format != 8 || after != 0) {
423
* xprop -notype -id wm_win
424
* _DT_WORKSPACE_INFO_ws0 = "One", "3", "0x2f2f4a",
425
* "0x63639c", "0x103", "1", "0x58044e"
430
for (i=0; i< (int) length; i++) {
431
if (*(data+i) != '\0') {
434
cnt++; /* count nulls to indicate field */
436
/* one past the null: */
437
char *q = (char *) (data+i+1);
439
if (sscanf(q, "0x%lx", &in) == 1) {
451
XGetWindowAttributes(dpy, twin, &attr);
452
if (twin != rootwin) {
453
if (attr.map_state != IsViewable) {
454
XMapWindow(dpy, twin);
456
XRaiseWindow(dpy, twin);
460
/* create image window: */
461
iswa.override_redirect = True;
462
iswa.backing_store = NotUseful;
463
iswa.save_under = False;
464
iswa.background_pixmap = ParentRelative;
465
visual.visualid = CopyFromParent;
467
iwin = XCreateWindow(dpy, twin, 0, 0, wdpy_x, wdpy_y,
468
0, depth, InputOutput, &visual, mask, &iswa);
470
rfbLog("snapshotting CDE backdrop ws%d 0x%lx -> "
471
"0x%lx ...\n", n, twin, iwin);
472
XMapWindow(dpy, iwin);
475
image[n] = XGetImage(dpy, iwin, 0, 0, wdpy_x, wdpy_y,
478
XDestroyWindow(dpy, iwin);
479
if (twin != rootwin) {
480
XLowerWindow(dpy, twin);
481
if (attr.map_state != IsViewable) {
482
XUnmapWindow(dpy, twin);
491
/* use black for low colors or failure */
492
pixel = BlackPixel(dpy, scr);
493
if (depth > 8 || strcmp(color, solid_default)) {
494
cmap = DefaultColormap (dpy, scr);
495
if (XParseColor(dpy, cmap, color, &cdef) &&
496
XAllocColor(dpy, cmap, &cdef)) {
499
rfbLog("error parsing/allocing color: %s\n", color);
503
rfbLog("setting solid backgrounds...\n");
505
for (n=0; n < nws; n++) {
506
Window twin = ws_wins[n];
507
if (image[n] == NULL) {
513
XSetWindowBackground(dpy, twin, pixel);
515
XMapWindow(dpy, expose);
517
XDestroyWindow(dpy, expose);
521
static void solid_gnome(char *color) {
527
char get_color[] = "gconftool-2 --get "
528
"/desktop/gnome/background/primary_color";
529
char set_color[] = "gconftool-2 --set "
530
"/desktop/gnome/background/primary_color --type string '%s'";
531
char get_option[] = "gconftool-2 --get "
532
"/desktop/gnome/background/picture_options";
533
char set_option[] = "gconftool-2 --set "
534
"/desktop/gnome/background/picture_options --type string '%s'";
535
static char *orig_color = NULL;
536
static char *orig_option = NULL;
543
orig_color = strdup("#FFFFFF");
546
orig_option = strdup("stretched");
548
if (strstr(orig_color, "'") != NULL) {
549
rfbLog("invalid color: %s\n", orig_color);
552
if (strstr(orig_option, "'") != NULL) {
553
rfbLog("invalid option: %s\n", orig_option);
556
cmd = (char *) malloc(strlen(set_option) - 2 +
557
strlen(orig_option) + 1);
558
sprintf(cmd, set_option, orig_option);
561
cmd = (char *) malloc(strlen(set_color) - 2 +
562
strlen(orig_color) + 1);
563
sprintf(cmd, set_color, orig_color);
572
orig_color = strdup(cmd_output(get_color));
576
if (*orig_color == '\0') {
577
orig_color = strdup("#FFFFFF");
579
if ((q = strchr(orig_color, '\n')) != NULL) {
586
orig_option = strdup(cmd_output(get_option));
590
if (*orig_option == '\0') {
591
orig_option = strdup("stretched");
593
if ((q = strchr(orig_option, '\n')) != NULL) {
597
if (strstr(color, "'") != NULL) {
598
rfbLog("invalid color: %s\n", color);
601
cmd = (char *) malloc(strlen(set_color) + strlen(color) + 1);
602
sprintf(cmd, set_color, color);
606
cmd = (char *) malloc(strlen(set_option) + strlen("none") + 1);
607
sprintf(cmd, set_option, "none");
613
static char *dcop_session(void) {
614
char *empty = strdup("");
619
char list_sessions[] = "dcop --user '%s' --list-sessions";
621
char *cmd, *host, *user = NULL;
622
char *out, *p, *ds, *dsn = NULL, *sess = NULL, *sess2 = NULL;
627
if (getenv("SESSION_MANAGER")) {
631
user = get_user_name();
632
if (strstr(user, "'") != NULL) {
633
rfbLog("invalid user: %s\n", user);
638
len = strlen(list_sessions) + strlen(user) + 1;
639
cmd = (char *) malloc(len);
640
sprintf(cmd, list_sessions, user);
642
out = strdup(cmd_output(cmd));
646
ds = DisplayString(dpy);
647
if (!ds || !strcmp(ds, "")) {
648
ds = getenv("DISPLAY");
654
p = strrchr(ds, '.');
657
dsn = strchr(ds, ':');
665
if (db) fprintf(stderr, "ds: %s\n", ds);
666
if (db) fprintf(stderr, "dsn: %s\n", dsn);
670
char *h2 = (char *) malloc(strlen(host) + 2 + 1);
671
sprintf(h2, "_%s_", host);
677
if (db) fprintf(stderr, "host: %s\n", host);
679
p = strtok(out, "\n");
681
char *q = strstr(p, ".DCOP");
682
if (db) fprintf(stderr, "p: %s\n", p);
686
if (strstr(q, host)) {
687
char *r = strstr(p, dsn);
689
if(r && !isalnum((int) *(r+n))) {
700
char *r = strstr(p, dsn);
702
if(r && !isalnum((int) *(r+n))) {
707
p = strtok(NULL, "\n");
712
if (!sess && sess2) {
715
if (!sess || strchr(sess, '\'')) {
716
if (sess) free(sess);
717
sess = strdup("--all-sessions");
719
len = strlen("--session ") + 2 + strlen(sess) + 1;
720
cmd = (char *) malloc(len);
721
sprintf(cmd, "--session '%s'", sess);
729
static void solid_kde(char *color) {
736
"dcop --user '%s' %s kdesktop KBackgroundIface setColor '%s' 1";
738
"dcop --user '%s' %s kdesktop KBackgroundIface setBackgroundEnabled 0";
740
"dcop --user '%s' %s kdesktop KBackgroundIface setBackgroundEnabled 1";
741
char *cmd, *user = NULL, *sess;
746
user = get_user_name();
747
if (strstr(user, "'") != NULL) {
748
rfbLog("invalid user: %s\n", user);
753
set_env("DISPLAY", DisplayString(dpy));
756
sess = dcop_session();
757
len = strlen(bg_on) + strlen(user) + strlen(sess) + 1;
758
cmd = (char *) malloc(len);
759
sprintf(cmd, bg_on, user, sess);
770
if (strstr(color, "'") != NULL) {
771
rfbLog("invalid color: %s\n", color);
775
sess = dcop_session();
777
len = strlen(set_color) + strlen(user) + strlen(sess) + strlen(color) + 1;
778
cmd = (char *) malloc(len);
779
sprintf(cmd, set_color, user, sess, color);
783
len = strlen(bg_off) + strlen(user) + strlen(sess) + 1;
784
cmd = (char *) malloc(len);
785
sprintf(cmd, bg_off, user, sess);
792
void kde_no_animate(int restore) {
798
char query_setting[] =
799
"kreadconfig --file kwinrc --group Windows --key AnimateMinimize";
801
"kwriteconfig --file kwinrc --group Windows --key AnimateMinimize --type bool false";
803
"kwriteconfig --file kwinrc --group Windows --key AnimateMinimize --type bool true";
804
char kwin_reconfigure[] =
805
"dcop --user '%s' %s kwin KWinInterface reconfigure";
806
char *cmd, *cmd2, *out, *user = NULL, *sess;
808
static int anim_state = 1;
812
if (ncache_keep_anims) {
817
if (anim_state == 1) {
821
user = get_user_name();
822
if (strstr(user, "'") != NULL) {
823
rfbLog("invalid user: %s\n", user);
828
sess = dcop_session();
830
len = strlen(kwin_reconfigure) + strlen(user) + strlen(sess) + 1;
831
cmd = (char *) malloc(len);
832
sprintf(cmd, kwin_reconfigure, user, sess);
834
rfbLog("Restoring KDE kwinrc settings.\n");
843
if (anim_state == 0) {
849
user = get_user_name();
850
if (strstr(user, "'") != NULL) {
851
rfbLog("invalid user: %s\n", user);
855
out = cmd_output(query_setting);
858
if (!out || strstr(out, "false")) {
860
rfbLog("********************************************************\n");
861
rfbLog("KDE kwinrc AnimateMinimize is false. Good.\n");
862
rfbLog("********************************************************\n");
869
rfbLog("********************************************************\n");
870
rfbLog("To improve the -ncache client-side caching performance\n");
871
rfbLog("temporarily setting KDE kwinrc AnimateMinimize to false.\n");
872
rfbLog("It will be reset for the next session or when VNC client\n");
873
rfbLog("disconnects. Or you can use the Control Center GUI to\n");
874
rfbLog("change it now (toggle its setting a few times):\n");
875
rfbLog(" Desktop -> Window Behavior -> Moving\n");
876
rfbLog("********************************************************\n");
879
set_env("DISPLAY", DisplayString(dpy));
881
sess = dcop_session();
882
len = strlen(kwin_reconfigure) + strlen(user) + strlen(sess) + 1;
883
cmd = (char *) malloc(len);
884
sprintf(cmd, kwin_reconfigure, user, sess);
886
len = 1 + strlen("sleep 10") + 2 + strlen(kwinrc_off) + 2 + strlen(cmd) + 2 + strlen("sleep 5") + 2 + strlen(kwinrc_on) + 3 + 1;
887
cmd2 = (char *) malloc(len);
889
sprintf(cmd2, "(sleep 10; %s; %s; sleep 5; %s) &", kwinrc_off, cmd, kwinrc_on);
899
void gnome_no_animate(void) {
903
char *guess_desktop(void) {
912
if (wmdt_str && *wmdt_str != '\0') {
915
if (strstr(s, "xfce")) {
918
if (strstr(s, "gnome") || strstr(s, "metacity")) {
921
if (strstr(s, "kde") || strstr(s, "kwin")) {
924
if (strstr(s, "cde")) {
934
prop = XInternAtom(dpy, "XFCE_DESKTOP_WINDOW", True);
935
if (prop != None) return "xfce";
937
/* special case windowmaker */
938
prop = XInternAtom(dpy, "_WINDOWMAKER_WM_PROTOCOLS", True);
939
if (prop != None) return "root";
941
prop = XInternAtom(dpy, "_WINDOWMAKER_COMMAND", True);
942
if (prop != None) return "root";
944
prop = XInternAtom(dpy, "NAUTILUS_DESKTOP_WINDOW_ID", True);
945
if (prop != None) return "gnome";
947
prop = XInternAtom(dpy, "KWIN_RUNNING", True);
949
prop = XInternAtom(dpy, "_KDE_RUNNING", True);
951
prop = XInternAtom(dpy, "KDE_DESKTOP_WINDOW", True);
952
if (prop != None) return "kde";
956
prop = XInternAtom(dpy, "_MOTIF_WM_INFO", True);
958
prop = XInternAtom(dpy, "_DT_WORKSPACE_LIST", True);
959
if (prop != None) return "cde";
965
XImage *solid_image(char *color) {
970
XImage *image = NULL;
971
unsigned long pixel = 0;
984
image = XGetImage(dpy, rootwin, 0, 0, wdpy_x, wdpy_y, AllPlanes,
990
pixel = get_pixel(color);
992
for (y=0; y<wdpy_y; y++) {
993
for (x=0; x<wdpy_x; x++) {
994
XPutPixel(image, x, y, pixel);
1001
void solid_bg(int restore) {
1002
static int desktop = -1;
1003
static int solid_on = 0;
1004
static char *prev_str;
1005
char *dtname, *color;
1009
if (started_as_root == 1 && users_list) {
1010
/* we are still root, don't try. */
1020
} else if (desktop == 1) {
1022
} else if (desktop == 2) {
1024
} else if (desktop == 3) {
1033
if (solid_on && !strcmp(prev_str, solid_str)) {
1036
if (strstr(solid_str, "guess:") == solid_str
1037
|| !strchr(solid_str, ':')) {
1038
dtname = guess_desktop();
1039
rfbLog("guessed desktop: %s\n", dtname);
1041
if (strstr(solid_str, "gnome:") == solid_str) {
1043
} else if (strstr(solid_str, "kde:") == solid_str) {
1045
} else if (strstr(solid_str, "cde:") == solid_str) {
1052
color = strchr(solid_str, ':');
1057
if (*color == '\0') {
1058
color = solid_default;
1064
last_color = strdup(color);
1066
if (!strcmp(dtname, "gnome")) {
1069
} else if (!strcmp(dtname, "kde")) {
1072
} else if (!strcmp(dtname, "cde")) {
1082
prev_str = strdup(solid_str);