San Mehat | a430b2b | 2014-09-23 08:30:51 -0700 | [diff] [blame] | 1 | /* |
| 2 | Copyright (C) 2002-2010 Karl J. Runge <runge@karlrunge.com> |
| 3 | All rights reserved. |
| 4 | |
| 5 | This file is part of x11vnc. |
| 6 | |
| 7 | x11vnc is free software; you can redistribute it and/or modify |
| 8 | it under the terms of the GNU General Public License as published by |
| 9 | the Free Software Foundation; either version 2 of the License, or (at |
| 10 | your option) any later version. |
| 11 | |
| 12 | x11vnc is distributed in the hope that it will be useful, |
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | GNU General Public License for more details. |
| 16 | |
| 17 | You should have received a copy of the GNU General Public License |
| 18 | along with x11vnc; if not, write to the Free Software |
| 19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA |
| 20 | or see <http://www.gnu.org/licenses/>. |
| 21 | |
| 22 | In addition, as a special exception, Karl J. Runge |
| 23 | gives permission to link the code of its release of x11vnc with the |
| 24 | OpenSSL project's "OpenSSL" library (or with modified versions of it |
| 25 | that use the same license as the "OpenSSL" library), and distribute |
| 26 | the linked executables. You must obey the GNU General Public License |
| 27 | in all respects for all of the code used other than "OpenSSL". If you |
| 28 | modify this file, you may extend this exception to your version of the |
| 29 | file, but you are not obligated to do so. If you do not wish to do |
| 30 | so, delete this exception statement from your version. |
| 31 | */ |
| 32 | |
| 33 | /* -- solid.c -- */ |
| 34 | |
| 35 | #include "x11vnc.h" |
| 36 | #include "win_utils.h" |
| 37 | #include "xwrappers.h" |
| 38 | #include "connections.h" |
| 39 | #include "cleanup.h" |
| 40 | #include "xevents.h" |
| 41 | |
| 42 | char *guess_desktop(void); |
| 43 | void solid_bg(int restore); |
| 44 | char *dbus_session(void); |
| 45 | |
| 46 | |
| 47 | static void usr_bin_path(int restore); |
| 48 | static int dt_cmd(char *cmd); |
| 49 | static char *cmd_output(char *cmd); |
| 50 | XImage *solid_root(char *color); |
| 51 | static void solid_cde(char *color); |
| 52 | static void solid_gnome(char *color); |
| 53 | static void solid_kde(char *color); |
| 54 | static void solid_macosx(int restore); |
| 55 | |
| 56 | static void usr_bin_path(int restore) { |
| 57 | static char *oldpath = NULL; |
| 58 | char *newpath; |
| 59 | char addpath[] = "/usr/bin:/bin:"; |
| 60 | |
| 61 | if (restore) { |
| 62 | if (oldpath) { |
| 63 | set_env("PATH", oldpath); |
| 64 | free(oldpath); |
| 65 | oldpath = NULL; |
| 66 | } |
| 67 | return; |
| 68 | } |
| 69 | |
| 70 | if (getenv("PATH")) { |
| 71 | oldpath = strdup(getenv("PATH")); |
| 72 | } else { |
| 73 | oldpath = strdup("/usr/bin"); |
| 74 | } |
| 75 | newpath = (char *) malloc(strlen(oldpath) + strlen(addpath) + 1); |
| 76 | newpath[0] = '\0'; |
| 77 | strcat(newpath, addpath); |
| 78 | strcat(newpath, oldpath); |
| 79 | set_env("PATH", newpath); |
| 80 | free(newpath); |
| 81 | } |
| 82 | |
| 83 | static int dt_cmd(char *cmd) { |
| 84 | int rc; |
| 85 | |
| 86 | RAWFB_RET(0) |
| 87 | |
| 88 | if (!cmd || *cmd == '\0') { |
| 89 | return 0; |
| 90 | } |
| 91 | |
| 92 | /* dt */ |
| 93 | if (no_external_cmds || !cmd_ok("dt")) { |
| 94 | rfbLog("cannot run external commands in -nocmds mode:\n"); |
| 95 | rfbLog(" \"%s\"\n", cmd); |
| 96 | rfbLog(" dt_cmd: returning 1\n"); |
| 97 | return 1; |
| 98 | } |
| 99 | |
| 100 | if (getenv("DISPLAY") == NULL) { |
| 101 | set_env("DISPLAY", DisplayString(dpy)); |
| 102 | } |
| 103 | |
| 104 | rfbLog("running command:\n"); |
| 105 | if (!quiet) { |
| 106 | fprintf(stderr, "\n %s\n\n", cmd); |
| 107 | } |
| 108 | usr_bin_path(0); |
| 109 | close_exec_fds(); |
| 110 | rc = system(cmd); |
| 111 | usr_bin_path(1); |
| 112 | |
| 113 | if (rc >= 256) { |
| 114 | rc = rc/256; |
| 115 | } |
| 116 | return rc; |
| 117 | } |
| 118 | |
| 119 | static char *cmd_output(char *cmd) { |
| 120 | FILE *p; |
| 121 | static char output[50000]; |
| 122 | char line[1024]; |
| 123 | int rc; |
| 124 | |
| 125 | if (!cmd || *cmd == '\0') { |
| 126 | return ""; |
| 127 | } |
| 128 | |
| 129 | if (no_external_cmds) { |
| 130 | rfbLog("cannot run external commands in -nocmds mode:\n"); |
| 131 | rfbLog(" \"%s\"\n", cmd); |
| 132 | rfbLog(" cmd_output: null string.\n"); |
| 133 | return ""; |
| 134 | } |
| 135 | |
| 136 | rfbLog("running pipe:\n"); |
| 137 | if (!quiet) { |
| 138 | fprintf(stderr, "\n %s\n\n", cmd); |
| 139 | } |
| 140 | usr_bin_path(0); |
| 141 | close_exec_fds(); |
| 142 | p = popen(cmd, "r"); |
| 143 | usr_bin_path(1); |
| 144 | |
| 145 | output[0] = '\0'; |
| 146 | |
| 147 | while (fgets(line, 1024, p) != NULL) { |
| 148 | if (strlen(output) + strlen(line) + 1 < 50000) { |
| 149 | strcat(output, line); |
| 150 | } |
| 151 | } |
| 152 | rc = pclose(p); |
| 153 | return(output); |
| 154 | } |
| 155 | |
| 156 | static char *last_color = NULL; |
| 157 | |
| 158 | unsigned long get_pixel(char *color) { |
| 159 | #if NO_X11 |
| 160 | return 0; |
| 161 | #else |
| 162 | XColor cdef; |
| 163 | Colormap cmap; |
| 164 | unsigned long pixel = BlackPixel(dpy, scr); |
| 165 | if (depth > 8 || strcmp(color, solid_default)) { |
| 166 | cmap = DefaultColormap (dpy, scr); |
| 167 | if (XParseColor(dpy, cmap, color, &cdef) && |
| 168 | XAllocColor(dpy, cmap, &cdef)) { |
| 169 | pixel = cdef.pixel; |
| 170 | } else { |
| 171 | rfbLog("error parsing/allocing color: %s\n", color); |
| 172 | } |
| 173 | } |
| 174 | return pixel; |
| 175 | #endif |
| 176 | } |
| 177 | |
| 178 | XImage *solid_root(char *color) { |
| 179 | #if NO_X11 |
| 180 | RAWFB_RET_VOID |
| 181 | if (!color) {} |
| 182 | return NULL; |
| 183 | #else |
| 184 | Window expose; |
| 185 | static XImage *image = NULL; |
| 186 | Pixmap pixmap; |
| 187 | XGCValues gcv; |
| 188 | GC gc; |
| 189 | XSetWindowAttributes swa; |
| 190 | Visual visual; |
| 191 | static unsigned long mask, pixel = 0; |
| 192 | |
| 193 | RAWFB_RET(NULL) |
| 194 | |
| 195 | if (subwin || window != rootwin) { |
| 196 | rfbLog("cannot set subwin to solid color, must be rootwin\n"); |
| 197 | return NULL; |
| 198 | } |
| 199 | |
| 200 | /* create the "clear" window just for generating exposures */ |
| 201 | swa.override_redirect = True; |
| 202 | swa.backing_store = NotUseful; |
| 203 | swa.save_under = False; |
| 204 | swa.background_pixmap = None; |
| 205 | visual.visualid = CopyFromParent; |
| 206 | mask = (CWOverrideRedirect|CWBackingStore|CWSaveUnder|CWBackPixmap); |
| 207 | expose = XCreateWindow(dpy, window, 0, 0, wdpy_x, wdpy_y, 0, depth, |
| 208 | InputOutput, &visual, mask, &swa); |
| 209 | |
| 210 | if (! color) { |
| 211 | |
| 212 | if (! image) { |
| 213 | /* whoops */ |
| 214 | XDestroyWindow(dpy, expose); |
| 215 | rfbLog("no root snapshot available.\n"); |
| 216 | return NULL; |
| 217 | } |
| 218 | |
| 219 | /* restore the root window from the XImage snapshot */ |
| 220 | pixmap = XCreatePixmap(dpy, window, wdpy_x, wdpy_y, depth); |
| 221 | |
| 222 | /* draw the image to a pixmap: */ |
| 223 | gcv.function = GXcopy; |
| 224 | gcv.plane_mask = AllPlanes; |
| 225 | gc = XCreateGC(dpy, window, GCFunction|GCPlaneMask, &gcv); |
| 226 | |
| 227 | XPutImage(dpy, pixmap, gc, image, 0, 0, 0, 0, wdpy_x, wdpy_y); |
| 228 | |
| 229 | gcv.foreground = gcv.background = BlackPixel(dpy, scr); |
| 230 | gc = XCreateGC(dpy, window, GCForeground|GCBackground, &gcv); |
| 231 | |
| 232 | rfbLog("restoring root snapshot...\n"); |
| 233 | /* set the pixmap as the bg: */ |
| 234 | XSetWindowBackgroundPixmap(dpy, window, pixmap); |
| 235 | XFreePixmap(dpy, pixmap); |
| 236 | XClearWindow(dpy, window); |
| 237 | XFlush_wr(dpy); |
| 238 | |
| 239 | /* generate exposures */ |
| 240 | XMapWindow(dpy, expose); |
| 241 | XSync(dpy, False); |
| 242 | XDestroyWindow(dpy, expose); |
| 243 | return NULL; |
| 244 | } |
| 245 | |
| 246 | if (! image) { |
| 247 | /* need to retrieve a snapshot of the root background: */ |
| 248 | Window iwin; |
| 249 | XSetWindowAttributes iswa; |
| 250 | |
| 251 | /* create image window: */ |
| 252 | iswa.override_redirect = True; |
| 253 | iswa.backing_store = NotUseful; |
| 254 | iswa.save_under = False; |
| 255 | iswa.background_pixmap = ParentRelative; |
| 256 | |
| 257 | iwin = XCreateWindow(dpy, window, 0, 0, wdpy_x, wdpy_y, 0, |
| 258 | depth, InputOutput, &visual, mask, &iswa); |
| 259 | |
| 260 | rfbLog("snapshotting background...\n"); |
| 261 | |
| 262 | XMapWindow(dpy, iwin); |
| 263 | XSync(dpy, False); |
| 264 | image = XGetImage(dpy, iwin, 0, 0, wdpy_x, wdpy_y, AllPlanes, |
| 265 | ZPixmap); |
| 266 | XSync(dpy, False); |
| 267 | XDestroyWindow(dpy, iwin); |
| 268 | rfbLog("done.\n"); |
| 269 | } |
| 270 | if (color == (char *) 0x1) { |
| 271 | /* caller will XDestroyImage it: */ |
| 272 | XImage *xi = image; |
| 273 | image = NULL; |
| 274 | return xi; |
| 275 | } |
| 276 | |
| 277 | /* use black for low colors or failure */ |
| 278 | pixel = get_pixel(color); |
| 279 | |
| 280 | rfbLog("setting solid background...\n"); |
| 281 | XSetWindowBackground(dpy, window, pixel); |
| 282 | XMapWindow(dpy, expose); |
| 283 | XSync(dpy, False); |
| 284 | XDestroyWindow(dpy, expose); |
| 285 | #endif /* NO_X11 */ |
| 286 | return NULL; |
| 287 | } |
| 288 | |
| 289 | static void solid_cde(char *color) { |
| 290 | #if NO_X11 |
| 291 | RAWFB_RET_VOID |
| 292 | if (!color) {} |
| 293 | return; |
| 294 | #else |
| 295 | int wsmax = 16; |
| 296 | static XImage *image[16]; |
| 297 | static Window ws_wins[16]; |
| 298 | static int nws = -1; |
| 299 | |
| 300 | Window expose; |
| 301 | Pixmap pixmap; |
| 302 | XGCValues gcv; |
| 303 | GC gc; |
| 304 | XSetWindowAttributes swa; |
| 305 | Visual visual; |
| 306 | unsigned long mask, pixel; |
| 307 | XColor cdef; |
| 308 | Colormap cmap; |
| 309 | int n; |
| 310 | |
| 311 | RAWFB_RET_VOID |
| 312 | |
| 313 | if (subwin || window != rootwin) { |
| 314 | rfbLog("cannot set subwin to solid color, must be rootwin\n"); |
| 315 | return; |
| 316 | } |
| 317 | |
| 318 | /* create the "clear" window just for generating exposures */ |
| 319 | swa.override_redirect = True; |
| 320 | swa.backing_store = NotUseful; |
| 321 | swa.save_under = False; |
| 322 | swa.background_pixmap = None; |
| 323 | visual.visualid = CopyFromParent; |
| 324 | mask = (CWOverrideRedirect|CWBackingStore|CWSaveUnder|CWBackPixmap); |
| 325 | expose = XCreateWindow(dpy, window, 0, 0, wdpy_x, wdpy_y, 0, depth, |
| 326 | InputOutput, &visual, mask, &swa); |
| 327 | |
| 328 | if (! color) { |
| 329 | /* restore the backdrop windows from the XImage snapshots */ |
| 330 | |
| 331 | for (n=0; n < nws; n++) { |
| 332 | Window twin; |
| 333 | |
| 334 | if (! image[n]) { |
| 335 | continue; |
| 336 | } |
| 337 | |
| 338 | twin = ws_wins[n]; |
| 339 | if (! twin) { |
| 340 | twin = rootwin; |
| 341 | } |
| 342 | if (! valid_window(twin, NULL, 0)) { |
| 343 | continue; |
| 344 | } |
| 345 | |
| 346 | pixmap = XCreatePixmap(dpy, twin, wdpy_x, wdpy_y, |
| 347 | depth); |
| 348 | |
| 349 | /* draw the image to a pixmap: */ |
| 350 | gcv.function = GXcopy; |
| 351 | gcv.plane_mask = AllPlanes; |
| 352 | gc = XCreateGC(dpy, twin, GCFunction|GCPlaneMask, &gcv); |
| 353 | |
| 354 | XPutImage(dpy, pixmap, gc, image[n], 0, 0, 0, 0, |
| 355 | wdpy_x, wdpy_y); |
| 356 | |
| 357 | gcv.foreground = gcv.background = BlackPixel(dpy, scr); |
| 358 | gc = XCreateGC(dpy, twin, GCForeground|GCBackground, |
| 359 | &gcv); |
| 360 | |
| 361 | rfbLog("restoring CDE ws%d snapshot to 0x%lx\n", |
| 362 | n, twin); |
| 363 | /* set the pixmap as the bg: */ |
| 364 | XSetWindowBackgroundPixmap(dpy, twin, pixmap); |
| 365 | XFreePixmap(dpy, pixmap); |
| 366 | XClearWindow(dpy, twin); |
| 367 | XFlush_wr(dpy); |
| 368 | } |
| 369 | |
| 370 | /* generate exposures */ |
| 371 | XMapWindow(dpy, expose); |
| 372 | XSync(dpy, False); |
| 373 | XDestroyWindow(dpy, expose); |
| 374 | return; |
| 375 | } |
| 376 | |
| 377 | if (nws < 0) { |
| 378 | /* need to retrieve snapshots of the ws backgrounds: */ |
| 379 | Window iwin, wm_win; |
| 380 | XSetWindowAttributes iswa; |
| 381 | Atom dt_list, wm_info, type; |
| 382 | int format; |
| 383 | unsigned long length, after; |
| 384 | unsigned char *data; |
| 385 | unsigned long *dp; /* crash on 64bit with int */ |
| 386 | |
| 387 | nws = 0; |
| 388 | |
| 389 | /* extract the hidden wm properties about backdrops: */ |
| 390 | |
| 391 | wm_info = XInternAtom(dpy, "_MOTIF_WM_INFO", True); |
| 392 | if (wm_info == None) { |
| 393 | return; |
| 394 | } |
| 395 | |
| 396 | XGetWindowProperty(dpy, rootwin, wm_info, 0L, 10L, False, |
| 397 | AnyPropertyType, &type, &format, &length, &after, &data); |
| 398 | |
| 399 | /* |
| 400 | * xprop -notype -root _MOTIF_WM_INFO |
| 401 | * _MOTIF_WM_INFO = 0x2, 0x580028 |
| 402 | */ |
| 403 | |
| 404 | if (length < 2 || format != 32 || after != 0) { |
| 405 | return; |
| 406 | } |
| 407 | |
| 408 | dp = (unsigned long *) data; |
| 409 | wm_win = (Window) *(dp+1); /* 2nd item. */ |
| 410 | |
| 411 | |
| 412 | dt_list = XInternAtom(dpy, "_DT_WORKSPACE_LIST", True); |
| 413 | if (dt_list == None) { |
| 414 | return; |
| 415 | } |
| 416 | |
| 417 | XGetWindowProperty(dpy, wm_win, dt_list, 0L, 10L, False, |
| 418 | AnyPropertyType, &type, &format, &length, &after, &data); |
| 419 | |
| 420 | nws = length; |
| 421 | |
| 422 | if (nws > wsmax) { |
| 423 | nws = wsmax; |
| 424 | } |
| 425 | if (nws < 0) { |
| 426 | nws = 0; |
| 427 | } |
| 428 | |
| 429 | rfbLog("special CDE win: 0x%lx, %d workspaces\n", wm_win, nws); |
| 430 | if (nws == 0) { |
| 431 | return; |
| 432 | } |
| 433 | |
| 434 | for (n=0; n<nws; n++) { |
| 435 | Atom ws_atom; |
| 436 | char tmp[32]; |
| 437 | Window twin; |
| 438 | XWindowAttributes attr; |
| 439 | int i, cnt; |
| 440 | |
| 441 | image[n] = NULL; |
| 442 | ws_wins[n] = 0x0; |
| 443 | |
| 444 | sprintf(tmp, "_DT_WORKSPACE_INFO_ws%d", n); |
| 445 | ws_atom = XInternAtom(dpy, tmp, False); |
| 446 | if (ws_atom == None) { |
| 447 | continue; |
| 448 | } |
| 449 | XGetWindowProperty(dpy, wm_win, ws_atom, 0L, 100L, |
| 450 | False, AnyPropertyType, &type, &format, &length, |
| 451 | &after, &data); |
| 452 | |
| 453 | if (format != 8 || after != 0) { |
| 454 | continue; |
| 455 | } |
| 456 | /* |
| 457 | * xprop -notype -id wm_win |
| 458 | * _DT_WORKSPACE_INFO_ws0 = "One", "3", "0x2f2f4a", |
| 459 | * "0x63639c", "0x103", "1", "0x58044e" |
| 460 | */ |
| 461 | |
| 462 | cnt = 0; |
| 463 | twin = 0x0; |
| 464 | for (i=0; i< (int) length; i++) { |
| 465 | if (*(data+i) != '\0') { |
| 466 | continue; |
| 467 | } |
| 468 | cnt++; /* count nulls to indicate field */ |
| 469 | if (cnt == 6) { |
| 470 | /* one past the null: */ |
| 471 | char *q = (char *) (data+i+1); |
| 472 | unsigned long in; |
| 473 | if (sscanf(q, "0x%lx", &in) == 1) { |
| 474 | twin = (Window) in; |
| 475 | break; |
| 476 | } |
| 477 | } |
| 478 | } |
| 479 | ws_wins[n] = twin; |
| 480 | |
| 481 | if (! twin) { |
| 482 | twin = rootwin; |
| 483 | } |
| 484 | |
| 485 | XGetWindowAttributes(dpy, twin, &attr); |
| 486 | if (twin != rootwin) { |
| 487 | if (attr.map_state != IsViewable) { |
| 488 | XMapWindow(dpy, twin); |
| 489 | } |
| 490 | XRaiseWindow(dpy, twin); |
| 491 | } |
| 492 | XSync(dpy, False); |
| 493 | |
| 494 | /* create image window: */ |
| 495 | iswa.override_redirect = True; |
| 496 | iswa.backing_store = NotUseful; |
| 497 | iswa.save_under = False; |
| 498 | iswa.background_pixmap = ParentRelative; |
| 499 | visual.visualid = CopyFromParent; |
| 500 | |
| 501 | iwin = XCreateWindow(dpy, twin, 0, 0, wdpy_x, wdpy_y, |
| 502 | 0, depth, InputOutput, &visual, mask, &iswa); |
| 503 | |
| 504 | rfbLog("snapshotting CDE backdrop ws%d 0x%lx -> " |
| 505 | "0x%lx ...\n", n, twin, iwin); |
| 506 | XMapWindow(dpy, iwin); |
| 507 | XSync(dpy, False); |
| 508 | |
| 509 | image[n] = XGetImage(dpy, iwin, 0, 0, wdpy_x, wdpy_y, |
| 510 | AllPlanes, ZPixmap); |
| 511 | XSync(dpy, False); |
| 512 | XDestroyWindow(dpy, iwin); |
| 513 | if (twin != rootwin) { |
| 514 | XLowerWindow(dpy, twin); |
| 515 | if (attr.map_state != IsViewable) { |
| 516 | XUnmapWindow(dpy, twin); |
| 517 | } |
| 518 | } |
| 519 | } |
| 520 | } |
| 521 | if (nws == 0) { |
| 522 | return; |
| 523 | } |
| 524 | |
| 525 | /* use black for low colors or failure */ |
| 526 | pixel = BlackPixel(dpy, scr); |
| 527 | if (depth > 8 || strcmp(color, solid_default)) { |
| 528 | cmap = DefaultColormap (dpy, scr); |
| 529 | if (XParseColor(dpy, cmap, color, &cdef) && |
| 530 | XAllocColor(dpy, cmap, &cdef)) { |
| 531 | pixel = cdef.pixel; |
| 532 | } else { |
| 533 | rfbLog("error parsing/allocing color: %s\n", color); |
| 534 | } |
| 535 | } |
| 536 | |
| 537 | rfbLog("setting solid backgrounds...\n"); |
| 538 | |
| 539 | for (n=0; n < nws; n++) { |
| 540 | Window twin = ws_wins[n]; |
| 541 | if (image[n] == NULL) { |
| 542 | continue; |
| 543 | } |
| 544 | if (! twin) { |
| 545 | twin = rootwin; |
| 546 | } |
| 547 | XSetWindowBackground(dpy, twin, pixel); |
| 548 | } |
| 549 | XMapWindow(dpy, expose); |
| 550 | XSync(dpy, False); |
| 551 | XDestroyWindow(dpy, expose); |
| 552 | #endif /* NO_X11 */ |
| 553 | } |
| 554 | |
| 555 | static char _dbus_str[1100]; |
| 556 | |
| 557 | char *dbus_session(void) { |
| 558 | char *dbus_env = getenv("DBUS_SESSION_BUS_ADDRESS"); |
| 559 | char tmp[1000]; |
| 560 | |
| 561 | if (dbus_env != NULL && strlen(dbus_env) > 0) { |
| 562 | return ""; |
| 563 | } |
| 564 | if (!dpy) { |
| 565 | return ""; |
| 566 | } |
| 567 | #if NO_X11 |
| 568 | return ""; |
| 569 | #else |
| 570 | { |
| 571 | Atom dbus_prop, dbus_pid; |
| 572 | Window r, w, *children; |
| 573 | int sbest = -1; |
| 574 | unsigned int ui; |
| 575 | int rc, i; |
| 576 | |
| 577 | memset(_dbus_str, 0, sizeof(_dbus_str)); |
| 578 | |
| 579 | X_LOCK; |
| 580 | dbus_prop = XInternAtom(dpy, "_DBUS_SESSION_BUS_ADDRESS", True); |
| 581 | dbus_pid = XInternAtom(dpy, "_DBUS_SESSION_BUS_PID", True); |
| 582 | X_UNLOCK; |
| 583 | if (dbus_prop == None) { |
| 584 | return ""; |
| 585 | } |
| 586 | |
| 587 | X_LOCK; |
| 588 | memset(tmp, 0, sizeof(tmp)); |
| 589 | get_prop(tmp, sizeof(tmp)-1, dbus_prop, None); |
| 590 | X_UNLOCK; |
| 591 | if (strcmp(tmp, "")) { |
| 592 | if (!strchr(tmp, '\'')) { |
| 593 | sprintf(_dbus_str, "env DBUS_SESSION_BUS_ADDRESS='%s'", tmp); |
| 594 | return _dbus_str; |
| 595 | } |
| 596 | } |
| 597 | |
| 598 | X_LOCK; |
| 599 | rc = XQueryTree_wr(dpy, rootwin, &r, &w, &children, &ui); |
| 600 | X_UNLOCK; |
| 601 | if (!rc || children == NULL || ui == 0) { |
| 602 | return ""; |
| 603 | } |
| 604 | for (i=0; i < (int) ui; i++) { |
| 605 | int pid = -1; |
| 606 | |
| 607 | X_LOCK; |
| 608 | memset(tmp, 0, sizeof(tmp)); |
| 609 | get_prop(tmp, sizeof(tmp)-1, dbus_prop, children[i]); |
| 610 | if (dbus_pid != None) { |
| 611 | Atom atype; |
| 612 | int aformat; |
| 613 | unsigned long nitems, bafter; |
| 614 | unsigned char *prop; |
| 615 | if (XGetWindowProperty(dpy, children[i], dbus_pid, |
| 616 | 0, 1, False, XA_CARDINAL, &atype, &aformat, |
| 617 | &nitems, &bafter, &prop) == Success |
| 618 | && atype == XA_CARDINAL) { |
| 619 | pid = *((int *) prop); |
| 620 | XFree_wr(prop); |
| 621 | } |
| 622 | } |
| 623 | X_UNLOCK; |
| 624 | |
| 625 | if (strcmp(tmp, "") && !strchr(tmp, '\'')) { |
| 626 | int score = 0; |
| 627 | if (1 < pid && pid < 10000000) { |
| 628 | struct stat sb; |
| 629 | char procfile[32]; |
| 630 | |
| 631 | sprintf(procfile, "/proc/%d", pid); |
| 632 | if (stat(procfile, &sb) == 0) { |
| 633 | score += 10000000; |
| 634 | } |
| 635 | score += pid; |
| 636 | } |
| 637 | if (getenv("X11VNC_DBUS_DEBUG")) fprintf(stderr, "win: 0x%lx pid: %8d score: %8d str: %s\n", children[i], pid, score, tmp); |
| 638 | if (score > sbest) { |
| 639 | sprintf(_dbus_str, "env DBUS_SESSION_BUS_ADDRESS='%s'", tmp); |
| 640 | sbest = score; |
| 641 | } |
| 642 | } |
| 643 | } |
| 644 | X_LOCK; |
| 645 | XFree_wr(children); |
| 646 | X_UNLOCK; |
| 647 | |
| 648 | return _dbus_str; |
| 649 | } |
| 650 | #endif |
| 651 | } |
| 652 | |
| 653 | static void solid_gnome(char *color) { |
| 654 | #if NO_X11 |
| 655 | RAWFB_RET_VOID |
| 656 | if (!color) {} |
| 657 | return; |
| 658 | #else |
| 659 | char get_color[] = "%s gconftool-2 --get " |
| 660 | "/desktop/gnome/background/primary_color"; |
| 661 | char set_color[] = "%s gconftool-2 --set --type string " |
| 662 | "/desktop/gnome/background/primary_color '%s'"; |
| 663 | char get_option[] = "%s gconftool-2 --get " |
| 664 | "/desktop/gnome/background/picture_options"; |
| 665 | char set_option[] = "%s gconftool-2 --set --type string " |
| 666 | "/desktop/gnome/background/picture_options '%s'"; |
| 667 | #if 0 |
| 668 | char get_shading[] = "%s gconftool-2 --get " |
| 669 | "/desktop/gnome/background/color_shading_type"; |
| 670 | char set_shading[] = "%s gconftool-2 --set --type string " |
| 671 | "/desktop/gnome/background/color_shading_type '%s'"; |
| 672 | char get_filename[] = "%s gconftool-2 --get " |
| 673 | "/desktop/gnome/background/picture_filename"; |
| 674 | char set_filename[] = "%s gconftool-2 --set --type string " |
| 675 | "/desktop/gnome/background/picture_filename '%s'"; |
| 676 | #endif |
| 677 | static char *orig_color = NULL; |
| 678 | static char *orig_option = NULL; |
| 679 | char *cmd, *dbus = ""; |
| 680 | |
| 681 | RAWFB_RET_VOID |
| 682 | |
| 683 | dbus = dbus_session(); |
| 684 | rfbLog("guessed dbus: %s\n", dbus); |
| 685 | |
| 686 | if (! color) { |
| 687 | if (! orig_color) { |
| 688 | orig_color = strdup("#FFFFFF"); |
| 689 | } |
| 690 | if (! orig_option) { |
| 691 | orig_option = strdup("stretched"); |
| 692 | } |
| 693 | if (strstr(orig_color, "'") != NULL) { |
| 694 | rfbLog("invalid color: %s\n", orig_color); |
| 695 | return; |
| 696 | } |
| 697 | if (strstr(orig_option, "'") != NULL) { |
| 698 | rfbLog("invalid option: %s\n", orig_option); |
| 699 | return; |
| 700 | } |
| 701 | cmd = (char *) malloc(strlen(set_option) - 2 + strlen(orig_option) + strlen(dbus) + 1); |
| 702 | sprintf(cmd, set_option, dbus, orig_option); |
| 703 | dt_cmd(cmd); |
| 704 | free(cmd); |
| 705 | cmd = (char *) malloc(strlen(set_color) - 2 + strlen(orig_color) + strlen(dbus) + 1); |
| 706 | sprintf(cmd, set_color, dbus, orig_color); |
| 707 | dt_cmd(cmd); |
| 708 | free(cmd); |
| 709 | return; |
| 710 | } |
| 711 | |
| 712 | if (! orig_color) { |
| 713 | char *q; |
| 714 | if (cmd_ok("dt")) { |
| 715 | cmd = (char *) malloc(strlen(get_color) + strlen(dbus) + 1); |
| 716 | sprintf(cmd, get_color, dbus); |
| 717 | orig_color = strdup(cmd_output(cmd)); |
| 718 | free(cmd); |
| 719 | } else { |
| 720 | orig_color = ""; |
| 721 | } |
| 722 | if (*orig_color == '\0') { |
| 723 | orig_color = strdup("#FFFFFF"); |
| 724 | } |
| 725 | if ((q = strchr(orig_color, '\n')) != NULL) { |
| 726 | *q = '\0'; |
| 727 | } |
| 728 | } |
| 729 | if (! orig_option) { |
| 730 | char *q; |
| 731 | if (cmd_ok("dt")) { |
| 732 | cmd = (char *) malloc(strlen(get_option) + strlen(dbus) + 1); |
| 733 | sprintf(cmd, get_option, dbus); |
| 734 | orig_option = strdup(cmd_output(cmd)); |
| 735 | free(cmd); |
| 736 | } else { |
| 737 | orig_color = ""; |
| 738 | } |
| 739 | if (*orig_option == '\0') { |
| 740 | orig_option = strdup("stretched"); |
| 741 | } |
| 742 | if ((q = strchr(orig_option, '\n')) != NULL) { |
| 743 | *q = '\0'; |
| 744 | } |
| 745 | } |
| 746 | if (strstr(color, "'") != NULL) { |
| 747 | rfbLog("invalid color: %s\n", color); |
| 748 | return; |
| 749 | } |
| 750 | cmd = (char *) malloc(strlen(set_color) + strlen(color) + strlen(dbus) + 1); |
| 751 | sprintf(cmd, set_color, dbus, color); |
| 752 | dt_cmd(cmd); |
| 753 | free(cmd); |
| 754 | |
| 755 | cmd = (char *) malloc(strlen(set_option) + strlen("none") + strlen(dbus) + 1); |
| 756 | sprintf(cmd, set_option, dbus, "none"); |
| 757 | dt_cmd(cmd); |
| 758 | free(cmd); |
| 759 | |
| 760 | #if 0 |
| 761 | cmd = (char *) malloc(strlen(set_filename) + strlen("none") + 1); |
| 762 | sprintf(cmd, set_filename, dbus, "none"); |
| 763 | dt_cmd(cmd); |
| 764 | free(cmd); |
| 765 | #endif |
| 766 | |
| 767 | #endif /* NO_X11 */ |
| 768 | } |
| 769 | |
| 770 | static void solid_xfce(char *color) { |
| 771 | #if NO_X11 |
| 772 | RAWFB_RET_VOID |
| 773 | if (!color) {} |
| 774 | return; |
| 775 | #else |
| 776 | char get_image_show[] = "%s xfconf-query -v -c xfce4-desktop -p /backdrop/screen0/monitor0/image-show"; |
| 777 | char set_image_show[] = "%s xfconf-query -v -c xfce4-desktop -p /backdrop/screen0/monitor0/image-show -s '%s'"; |
| 778 | char get_color_style[] = "%s xfconf-query -v -c xfce4-desktop -p /backdrop/screen0/monitor0/color-style"; |
| 779 | char set_color_style[] = "%s xfconf-query -v -c xfce4-desktop -p /backdrop/screen0/monitor0/color-style -s '%s'"; |
| 780 | |
| 781 | static char *orig_image_show = NULL; |
| 782 | static char *orig_color_style = NULL; |
| 783 | char *cmd, *dbus = ""; |
| 784 | |
| 785 | RAWFB_RET_VOID |
| 786 | |
| 787 | dbus = dbus_session(); |
| 788 | rfbLog("guessed dbus: %s\n", dbus); |
| 789 | |
| 790 | if (! color) { |
| 791 | if (! orig_image_show) { |
| 792 | orig_image_show = "true"; |
| 793 | } |
| 794 | if (! orig_color_style) { |
| 795 | orig_color_style = "0"; |
| 796 | } |
| 797 | if (strstr(orig_image_show, "'") != NULL) { |
| 798 | rfbLog("invalid image show: %s\n", orig_image_show); |
| 799 | return; |
| 800 | } |
| 801 | if (strstr(orig_color_style, "'") != NULL) { |
| 802 | rfbLog("invalid color style: %s\n", orig_color_style); |
| 803 | return; |
| 804 | } |
| 805 | if (orig_image_show[0] != '\0') { |
| 806 | cmd = (char *) malloc(strlen(set_image_show) - 2 + strlen(orig_image_show) + strlen(dbus) + 1); |
| 807 | sprintf(cmd, set_image_show, dbus, orig_image_show); |
| 808 | dt_cmd(cmd); |
| 809 | free(cmd); |
| 810 | } |
| 811 | if (orig_color_style[0] != '\0') { |
| 812 | cmd = (char *) malloc(strlen(set_color_style) - 2 + strlen(orig_color_style) + strlen(dbus) + 1); |
| 813 | sprintf(cmd, set_color_style, dbus, orig_color_style); |
| 814 | dt_cmd(cmd); |
| 815 | free(cmd); |
| 816 | } |
| 817 | return; |
| 818 | } |
| 819 | |
| 820 | if (! orig_image_show) { |
| 821 | char *q; |
| 822 | orig_image_show = ""; |
| 823 | if (cmd_ok("dt")) { |
| 824 | cmd = (char *) malloc(strlen(get_image_show) + strlen(dbus) + 1); |
| 825 | sprintf(cmd, get_image_show, dbus); |
| 826 | orig_image_show = strdup(cmd_output(cmd)); |
| 827 | if ((q = strrchr(orig_image_show, '\n')) != NULL) { |
| 828 | *q = '\0'; |
| 829 | } |
| 830 | fprintf(stderr, "get_image_show returned: '%s'\n\n", orig_image_show); |
| 831 | free(cmd); |
| 832 | if (strcasecmp(orig_image_show, "false") && strcasecmp(orig_image_show, "true")) { |
| 833 | fprintf(stderr, "unrecognized image_show, disabling.\n"); |
| 834 | free(orig_image_show); |
| 835 | orig_image_show = ""; |
| 836 | } |
| 837 | } |
| 838 | } |
| 839 | if (! orig_color_style) { |
| 840 | char *q; |
| 841 | orig_color_style = ""; |
| 842 | if (cmd_ok("dt")) { |
| 843 | cmd = (char *) malloc(strlen(get_color_style) + strlen(dbus) + 1); |
| 844 | sprintf(cmd, get_color_style, dbus); |
| 845 | orig_color_style = strdup(cmd_output(cmd)); |
| 846 | if ((q = strrchr(orig_color_style, '\n')) != NULL) { |
| 847 | *q = '\0'; |
| 848 | } |
| 849 | fprintf(stderr, "get_color_style returned: '%s'\n\n", orig_color_style); |
| 850 | free(cmd); |
| 851 | if (strlen(orig_color_style) > 1 || !isdigit((unsigned char) (*orig_color_style))) { |
| 852 | fprintf(stderr, "unrecognized color_style, disabling.\n"); |
| 853 | free(orig_color_style); |
| 854 | orig_color_style = ""; |
| 855 | } |
| 856 | } |
| 857 | } |
| 858 | |
| 859 | if (strstr(color, "'") != NULL) { |
| 860 | rfbLog("invalid color: %s\n", color); |
| 861 | return; |
| 862 | } |
| 863 | |
| 864 | cmd = (char *) malloc(strlen(set_color_style) + strlen("0") + strlen(dbus) + 1); |
| 865 | sprintf(cmd, set_color_style, dbus, "0"); |
| 866 | dt_cmd(cmd); |
| 867 | free(cmd); |
| 868 | |
| 869 | cmd = (char *) malloc(strlen(set_image_show) + strlen("false") + strlen(dbus) + 1); |
| 870 | sprintf(cmd, set_image_show, dbus, "false"); |
| 871 | dt_cmd(cmd); |
| 872 | free(cmd); |
| 873 | |
| 874 | #endif /* NO_X11 */ |
| 875 | } |
| 876 | |
| 877 | |
| 878 | static char *dcop_session(void) { |
| 879 | char *empty = strdup(""); |
| 880 | #if NO_X11 |
| 881 | RAWFB_RET(empty); |
| 882 | return empty; |
| 883 | #else |
| 884 | char list_sessions[] = "dcop --user '%s' --list-sessions"; |
| 885 | int len; |
| 886 | char *cmd, *host, *user = NULL; |
| 887 | char *out, *p, *ds, *dsn = NULL, *sess = NULL, *sess2 = NULL; |
| 888 | int db = 0; |
| 889 | |
| 890 | RAWFB_RET(empty); |
| 891 | |
| 892 | if (getenv("SESSION_MANAGER")) { |
| 893 | return empty; |
| 894 | } |
| 895 | |
| 896 | user = get_user_name(); |
| 897 | if (strstr(user, "'") != NULL) { |
| 898 | rfbLog("invalid user: %s\n", user); |
| 899 | free(user); |
| 900 | return empty; |
| 901 | } |
| 902 | |
| 903 | len = strlen(list_sessions) + strlen(user) + 1; |
| 904 | cmd = (char *) malloc(len); |
| 905 | sprintf(cmd, list_sessions, user); |
| 906 | |
| 907 | out = strdup(cmd_output(cmd)); |
| 908 | free(cmd); |
| 909 | free(user); |
| 910 | |
| 911 | ds = DisplayString(dpy); |
| 912 | if (!ds || !strcmp(ds, "")) { |
| 913 | ds = getenv("DISPLAY"); |
| 914 | } |
| 915 | if (!ds) { |
| 916 | ds = ":0"; |
| 917 | } |
| 918 | ds = strdup(ds); |
| 919 | p = strrchr(ds, '.'); |
| 920 | if (p) *p = '\0'; |
| 921 | |
| 922 | dsn = strchr(ds, ':'); |
| 923 | if (dsn) { |
| 924 | *dsn = '_'; |
| 925 | } else { |
| 926 | free(ds); |
| 927 | ds = strdup("_0"); |
| 928 | dsn = ds; |
| 929 | } |
| 930 | if (db) fprintf(stderr, "ds: %s\n", ds); |
| 931 | if (db) fprintf(stderr, "dsn: %s\n", dsn); |
| 932 | |
| 933 | host = this_host(); |
| 934 | if (host) { |
| 935 | char *h2 = (char *) malloc(strlen(host) + 2 + 1); |
| 936 | sprintf(h2, "_%s_", host); |
| 937 | free(host); |
| 938 | host = h2; |
| 939 | } else { |
| 940 | host = strdup(""); |
| 941 | } |
| 942 | if (db) fprintf(stderr, "host: %s\n", host); |
| 943 | |
| 944 | p = strtok(out, "\n"); |
| 945 | while (p) { |
| 946 | char *q = strstr(p, ".DCOP"); |
| 947 | if (db) fprintf(stderr, "p: %s\n", p); |
| 948 | if (q == NULL) { |
| 949 | ; |
| 950 | } else if (host) { |
| 951 | if (strstr(q, host)) { |
| 952 | char *r = strstr(p, dsn); |
| 953 | int n = strlen(dsn); |
| 954 | if(r && !isalnum((int) *(r+n))) { |
| 955 | sess = strdup(q); |
| 956 | break; |
| 957 | } else { |
| 958 | if (sess2) { |
| 959 | free(sess2); |
| 960 | } |
| 961 | sess2 = strdup(q); |
| 962 | } |
| 963 | } |
| 964 | } else { |
| 965 | char *r = strstr(p, dsn); |
| 966 | int n = strlen(dsn); |
| 967 | if(r && !isalnum((int) *(r+n))) { |
| 968 | sess = strdup(q); |
| 969 | break; |
| 970 | } |
| 971 | } |
| 972 | p = strtok(NULL, "\n"); |
| 973 | } |
| 974 | free(ds); |
| 975 | free(out); |
| 976 | free(host); |
| 977 | if (!sess && sess2) { |
| 978 | sess = sess2; |
| 979 | } |
| 980 | if (!sess || strchr(sess, '\'')) { |
| 981 | if (sess) free(sess); |
| 982 | sess = strdup("--all-sessions"); |
| 983 | } else { |
| 984 | len = strlen("--session ") + 2 + strlen(sess) + 1; |
| 985 | cmd = (char *) malloc(len); |
| 986 | sprintf(cmd, "--session '%s'", sess); |
| 987 | free(sess); |
| 988 | sess = cmd; |
| 989 | } |
| 990 | return sess; |
| 991 | #endif |
| 992 | } |
| 993 | |
| 994 | static void solid_kde(char *color) { |
| 995 | #if NO_X11 |
| 996 | RAWFB_RET_VOID |
| 997 | if (!color) {} |
| 998 | return; |
| 999 | #else |
| 1000 | char set_color[] = |
| 1001 | "dcop --user '%s' %s kdesktop KBackgroundIface setColor '%s' 1"; |
| 1002 | char bg_off[] = |
| 1003 | "dcop --user '%s' %s kdesktop KBackgroundIface setBackgroundEnabled 0"; |
| 1004 | char bg_on[] = |
| 1005 | "dcop --user '%s' %s kdesktop KBackgroundIface setBackgroundEnabled 1"; |
| 1006 | char *cmd, *user = NULL, *sess; |
| 1007 | int len; |
| 1008 | |
| 1009 | RAWFB_RET_VOID |
| 1010 | |
| 1011 | user = get_user_name(); |
| 1012 | if (strstr(user, "'") != NULL) { |
| 1013 | rfbLog("invalid user: %s\n", user); |
| 1014 | free(user); |
| 1015 | return; |
| 1016 | } |
| 1017 | |
| 1018 | set_env("DISPLAY", DisplayString(dpy)); |
| 1019 | |
| 1020 | if (! color) { |
| 1021 | sess = dcop_session(); |
| 1022 | len = strlen(bg_on) + strlen(user) + strlen(sess) + 1; |
| 1023 | cmd = (char *) malloc(len); |
| 1024 | sprintf(cmd, bg_on, user, sess); |
| 1025 | |
| 1026 | dt_cmd(cmd); |
| 1027 | |
| 1028 | free(cmd); |
| 1029 | free(user); |
| 1030 | free(sess); |
| 1031 | |
| 1032 | return; |
| 1033 | } |
| 1034 | |
| 1035 | if (strstr(color, "'") != NULL) { |
| 1036 | rfbLog("invalid color: %s\n", color); |
| 1037 | return; |
| 1038 | } |
| 1039 | |
| 1040 | sess = dcop_session(); |
| 1041 | |
| 1042 | len = strlen(set_color) + strlen(user) + strlen(sess) + strlen(color) + 1; |
| 1043 | cmd = (char *) malloc(len); |
| 1044 | sprintf(cmd, set_color, user, sess, color); |
| 1045 | dt_cmd(cmd); |
| 1046 | free(cmd); |
| 1047 | |
| 1048 | len = strlen(bg_off) + strlen(user) + strlen(sess) + 1; |
| 1049 | cmd = (char *) malloc(len); |
| 1050 | sprintf(cmd, bg_off, user, sess); |
| 1051 | dt_cmd(cmd); |
| 1052 | free(cmd); |
| 1053 | free(user); |
| 1054 | #endif /* NO_X11 */ |
| 1055 | } |
| 1056 | |
| 1057 | void kde_no_animate(int restore) { |
| 1058 | #if NO_X11 |
| 1059 | if (!restore) {} |
| 1060 | RAWFB_RET_VOID |
| 1061 | return; |
| 1062 | #else |
| 1063 | char query_setting[] = |
| 1064 | "kreadconfig --file kwinrc --group Windows --key AnimateMinimize"; |
| 1065 | char kwinrc_off[] = |
| 1066 | "kwriteconfig --file kwinrc --group Windows --key AnimateMinimize --type bool false"; |
| 1067 | char kwinrc_on[] = |
| 1068 | "kwriteconfig --file kwinrc --group Windows --key AnimateMinimize --type bool true"; |
| 1069 | char kwin_reconfigure[] = |
| 1070 | "dcop --user '%s' %s kwin KWinInterface reconfigure"; |
| 1071 | char *cmd, *cmd2, *out, *user = NULL, *sess; |
| 1072 | int len; |
| 1073 | static int anim_state = 1; |
| 1074 | |
| 1075 | RAWFB_RET_VOID |
| 1076 | |
| 1077 | if (ncache_keep_anims) { |
| 1078 | return; |
| 1079 | } |
| 1080 | |
| 1081 | if (restore) { |
| 1082 | if (anim_state == 1) { |
| 1083 | return; |
| 1084 | } |
| 1085 | |
| 1086 | user = get_user_name(); |
| 1087 | if (strstr(user, "'") != NULL) { |
| 1088 | rfbLog("invalid user: %s\n", user); |
| 1089 | free(user); |
| 1090 | return; |
| 1091 | } |
| 1092 | |
| 1093 | sess = dcop_session(); |
| 1094 | |
| 1095 | len = strlen(kwin_reconfigure) + strlen(user) + strlen(sess) + 1; |
| 1096 | cmd = (char *) malloc(len); |
| 1097 | sprintf(cmd, kwin_reconfigure, user, sess); |
| 1098 | rfbLog("\n"); |
| 1099 | rfbLog("Restoring KDE kwinrc settings.\n"); |
| 1100 | rfbLog("\n"); |
| 1101 | dt_cmd(cmd); |
| 1102 | free(cmd); |
| 1103 | free(user); |
| 1104 | free(sess); |
| 1105 | anim_state = 1; |
| 1106 | return; |
| 1107 | } else { |
| 1108 | if (anim_state == 0) { |
| 1109 | return; |
| 1110 | } |
| 1111 | anim_state = 0; |
| 1112 | } |
| 1113 | |
| 1114 | user = get_user_name(); |
| 1115 | if (strstr(user, "'") != NULL) { |
| 1116 | rfbLog("invalid user: %s\n", user); |
| 1117 | free(user); |
| 1118 | return; |
| 1119 | } |
| 1120 | out = cmd_output(query_setting); |
| 1121 | |
| 1122 | |
| 1123 | if (!out || strstr(out, "false")) { |
| 1124 | rfbLog("\n"); |
| 1125 | rfbLog("********************************************************\n"); |
| 1126 | rfbLog("KDE kwinrc AnimateMinimize is false. Good.\n"); |
| 1127 | rfbLog("********************************************************\n"); |
| 1128 | rfbLog("\n"); |
| 1129 | free(user); |
| 1130 | return; |
| 1131 | } |
| 1132 | |
| 1133 | rfbLog("\n"); |
| 1134 | rfbLog("********************************************************\n"); |
| 1135 | rfbLog("To improve the -ncache client-side caching performance\n"); |
| 1136 | rfbLog("temporarily setting KDE kwinrc AnimateMinimize to false.\n"); |
| 1137 | rfbLog("It will be reset for the next session or when VNC client\n"); |
| 1138 | rfbLog("disconnects. Or you can use the Control Center GUI to\n"); |
| 1139 | rfbLog("change it now (toggle its setting a few times):\n"); |
| 1140 | rfbLog(" Desktop -> Window Behavior -> Moving\n"); |
| 1141 | rfbLog("********************************************************\n"); |
| 1142 | rfbLog("\n"); |
| 1143 | |
| 1144 | set_env("DISPLAY", DisplayString(dpy)); |
| 1145 | |
| 1146 | sess = dcop_session(); |
| 1147 | len = strlen(kwin_reconfigure) + strlen(user) + strlen(sess) + 1; |
| 1148 | cmd = (char *) malloc(len); |
| 1149 | sprintf(cmd, kwin_reconfigure, user, sess); |
| 1150 | |
| 1151 | len = 1 + strlen("sleep 10") + 2 + strlen(kwinrc_off) + 2 + strlen(cmd) + 2 + strlen("sleep 5") + 2 + strlen(kwinrc_on) + 3 + 1; |
| 1152 | cmd2 = (char *) malloc(len); |
| 1153 | |
| 1154 | sprintf(cmd2, "(sleep 10; %s; %s; sleep 5; %s) &", kwinrc_off, cmd, kwinrc_on); |
| 1155 | |
| 1156 | dt_cmd(cmd2); |
| 1157 | free(cmd); |
| 1158 | free(cmd2); |
| 1159 | free(user); |
| 1160 | free(sess); |
| 1161 | #endif /* NO_X11 */ |
| 1162 | } |
| 1163 | |
| 1164 | void gnome_no_animate(void) { |
| 1165 | ; |
| 1166 | } |
| 1167 | |
| 1168 | static pid_t solid_macosx_pid = 0; |
| 1169 | extern char macosx_solid_background[]; |
| 1170 | |
| 1171 | static void solid_macosx(int restore) { |
| 1172 | char tmp[] = "/tmp/macosx_solid_background.XXXXXX"; |
| 1173 | pid_t pid, parent = getpid(); |
| 1174 | |
| 1175 | if (restore) { |
| 1176 | rfbLog("restore pid: %d\n", (int) solid_macosx_pid); |
| 1177 | if (solid_macosx_pid > 0) { |
| 1178 | #if 0 |
| 1179 | int i, status; |
| 1180 | #endif |
| 1181 | rfbLog("kill -TERM macosx_solid_background helper pid: %d\n", (int) solid_macosx_pid); |
| 1182 | kill(solid_macosx_pid, SIGTERM); |
| 1183 | #if 0 |
| 1184 | #if LIBVNCSERVER_HAVE_SYS_WAIT_H |
| 1185 | #if LIBVNCSERVER_HAVE_WAITPID |
| 1186 | for (i=0; i < 7; i++) { |
| 1187 | usleep(1000 * 1000); |
| 1188 | waitpid(solid_macosx_pid, &status, WNOHANG); |
| 1189 | if (kill(solid_macosx_pid, 0) != 0) { |
| 1190 | break; |
| 1191 | } |
| 1192 | } |
| 1193 | #endif |
| 1194 | #endif |
| 1195 | #endif |
| 1196 | solid_macosx_pid = 0; |
| 1197 | } |
| 1198 | return; |
| 1199 | } |
| 1200 | if (no_external_cmds || !cmd_ok("dt")) { |
| 1201 | return; |
| 1202 | } |
| 1203 | #if LIBVNCSERVER_HAVE_FORK |
| 1204 | pid = fork(); |
| 1205 | |
| 1206 | if (pid == -1) { |
| 1207 | perror("fork"); |
| 1208 | return; |
| 1209 | } |
| 1210 | if (pid == 0) { |
| 1211 | int fd = mkstemp(tmp); |
| 1212 | #if LIBVNCSERVER_HAVE_SETSID |
| 1213 | setsid(); |
| 1214 | #else |
| 1215 | setpgrp(); |
| 1216 | #endif |
| 1217 | if (fd >= 0) { |
| 1218 | char num[32]; |
| 1219 | write(fd, macosx_solid_background, strlen(macosx_solid_background)); |
| 1220 | close(fd); |
| 1221 | sprintf(num, "%d", (int) parent); |
| 1222 | set_env("SS_WATCH_PID", num); |
| 1223 | execlp("/bin/sh", "/bin/sh", tmp, (char *) NULL); |
| 1224 | } |
| 1225 | exit(1); |
| 1226 | } |
| 1227 | solid_macosx_pid = pid; |
| 1228 | rfbLog("macosx_solid_background helper pid: %d\n", (int) solid_macosx_pid); |
| 1229 | usleep(2750 * 1000); |
| 1230 | unlink(tmp); |
| 1231 | #endif |
| 1232 | } |
| 1233 | |
| 1234 | char *guess_desktop(void) { |
| 1235 | #if NO_X11 |
| 1236 | RAWFB_RET("root") |
| 1237 | return "root"; |
| 1238 | #else |
| 1239 | Atom prop; |
| 1240 | |
| 1241 | RAWFB_RET("root") |
| 1242 | |
| 1243 | if (wmdt_str && *wmdt_str != '\0') { |
| 1244 | char *s = wmdt_str; |
| 1245 | lowercase(s); |
| 1246 | if (strstr(s, "xfce")) { |
| 1247 | return "xfce"; |
| 1248 | } |
| 1249 | if (strstr(s, "gnome") || strstr(s, "metacity")) { |
| 1250 | return "gnome"; |
| 1251 | } |
| 1252 | if (strstr(s, "kde") || strstr(s, "kwin")) { |
| 1253 | return "kde"; |
| 1254 | } |
| 1255 | if (strstr(s, "cde")) { |
| 1256 | return "cde"; |
| 1257 | } |
| 1258 | return "root"; |
| 1259 | } |
| 1260 | |
| 1261 | if (! dpy) { |
| 1262 | return ""; |
| 1263 | } |
| 1264 | |
| 1265 | prop = XInternAtom(dpy, "XFCE_DESKTOP_WINDOW", True); |
| 1266 | if (prop != None) return "xfce"; |
| 1267 | |
| 1268 | /* special case windowmaker */ |
| 1269 | prop = XInternAtom(dpy, "_WINDOWMAKER_WM_PROTOCOLS", True); |
| 1270 | if (prop != None) return "root"; |
| 1271 | |
| 1272 | prop = XInternAtom(dpy, "_WINDOWMAKER_COMMAND", True); |
| 1273 | if (prop != None) return "root"; |
| 1274 | |
| 1275 | prop = XInternAtom(dpy, "NAUTILUS_DESKTOP_WINDOW_ID", True); |
| 1276 | if (prop != None) return "gnome"; |
| 1277 | |
| 1278 | prop = XInternAtom(dpy, "KWIN_RUNNING", True); |
| 1279 | if (prop != None) { |
| 1280 | prop = XInternAtom(dpy, "_KDE_RUNNING", True); |
| 1281 | if (prop != None) { |
| 1282 | prop = XInternAtom(dpy, "KDE_DESKTOP_WINDOW", True); |
| 1283 | if (prop != None) return "kde"; |
| 1284 | } |
| 1285 | } |
| 1286 | |
| 1287 | prop = XInternAtom(dpy, "_MOTIF_WM_INFO", True); |
| 1288 | if (prop != None) { |
| 1289 | prop = XInternAtom(dpy, "_DT_WORKSPACE_LIST", True); |
| 1290 | if (prop != None) return "cde"; |
| 1291 | } |
| 1292 | return "root"; |
| 1293 | #endif /* NO_X11 */ |
| 1294 | } |
| 1295 | |
| 1296 | XImage *solid_image(char *color) { |
| 1297 | #if NO_X11 |
| 1298 | RAWFB_RET(NULL) |
| 1299 | return NULL; |
| 1300 | #else |
| 1301 | XImage *image = NULL; |
| 1302 | unsigned long pixel = 0; |
| 1303 | int x, y; |
| 1304 | |
| 1305 | RAWFB_RET(NULL) |
| 1306 | |
| 1307 | if (!color) { |
| 1308 | color = last_color; |
| 1309 | } |
| 1310 | |
| 1311 | if (!color) { |
| 1312 | return NULL; |
| 1313 | } |
| 1314 | |
| 1315 | image = XGetImage(dpy, rootwin, 0, 0, wdpy_x, wdpy_y, AllPlanes, |
| 1316 | ZPixmap); |
| 1317 | |
| 1318 | if (!image) { |
| 1319 | return NULL; |
| 1320 | } |
| 1321 | pixel = get_pixel(color); |
| 1322 | |
| 1323 | for (y=0; y<wdpy_y; y++) { |
| 1324 | for (x=0; x<wdpy_x; x++) { |
| 1325 | XPutPixel(image, x, y, pixel); |
| 1326 | } |
| 1327 | } |
| 1328 | return image; |
| 1329 | #endif /* NO_X11 */ |
| 1330 | } |
| 1331 | |
| 1332 | void solid_bg(int restore) { |
| 1333 | static int desktop = -1; |
| 1334 | static int solid_on = 0; |
| 1335 | static char *prev_str; |
| 1336 | char *dtname, *color; |
| 1337 | |
| 1338 | if (started_as_root == 1 && users_list) { |
| 1339 | /* we are still root, don't try. */ |
| 1340 | return; |
| 1341 | } |
| 1342 | |
| 1343 | if (macosx_console) { |
| 1344 | solid_macosx(restore); |
| 1345 | return; |
| 1346 | } |
| 1347 | |
| 1348 | RAWFB_RET_VOID |
| 1349 | |
| 1350 | if (restore) { |
| 1351 | if (! solid_on) { |
| 1352 | return; |
| 1353 | } |
| 1354 | if (desktop == 0) { |
| 1355 | solid_root(NULL); |
| 1356 | } else if (desktop == 1) { |
| 1357 | solid_gnome(NULL); |
| 1358 | } else if (desktop == 2) { |
| 1359 | solid_kde(NULL); |
| 1360 | } else if (desktop == 3) { |
| 1361 | solid_cde(NULL); |
| 1362 | } else if (desktop == 4) { |
| 1363 | solid_xfce(NULL); |
| 1364 | } |
| 1365 | solid_on = 0; |
| 1366 | return; |
| 1367 | } |
| 1368 | if (! solid_str) { |
| 1369 | return; |
| 1370 | } |
| 1371 | if (solid_on && !strcmp(prev_str, solid_str)) { |
| 1372 | return; |
| 1373 | } |
| 1374 | if (strstr(solid_str, "guess:") == solid_str |
| 1375 | || !strchr(solid_str, ':')) { |
| 1376 | dtname = guess_desktop(); |
| 1377 | rfbLog("guessed desktop: %s\n", dtname); |
| 1378 | } else { |
| 1379 | if (strstr(solid_str, "gnome:") == solid_str) { |
| 1380 | dtname = "gnome"; |
| 1381 | } else if (strstr(solid_str, "kde:") == solid_str) { |
| 1382 | dtname = "kde"; |
| 1383 | } else if (strstr(solid_str, "cde:") == solid_str) { |
| 1384 | dtname = "cde"; |
| 1385 | } else if (strstr(solid_str, "xfce:") == solid_str) { |
| 1386 | dtname = "xfce"; |
| 1387 | } else { |
| 1388 | dtname = "root"; |
| 1389 | } |
| 1390 | } |
| 1391 | |
| 1392 | color = strchr(solid_str, ':'); |
| 1393 | if (! color) { |
| 1394 | color = solid_str; |
| 1395 | } else { |
| 1396 | color++; |
| 1397 | if (*color == '\0') { |
| 1398 | color = solid_default; |
| 1399 | } |
| 1400 | } |
| 1401 | if (last_color) { |
| 1402 | free(last_color); |
| 1403 | } |
| 1404 | last_color = strdup(color); |
| 1405 | |
| 1406 | if (!strcmp(dtname, "gnome")) { |
| 1407 | desktop = 1; |
| 1408 | solid_gnome(color); |
| 1409 | } else if (!strcmp(dtname, "kde")) { |
| 1410 | desktop = 2; |
| 1411 | solid_kde(color); |
| 1412 | } else if (!strcmp(dtname, "cde")) { |
| 1413 | desktop = 3; |
| 1414 | solid_cde(color); |
| 1415 | } else if (!strcmp(dtname, "xfce")) { |
| 1416 | desktop = 4; |
| 1417 | solid_xfce(color); |
| 1418 | } else { |
| 1419 | desktop = 0; |
| 1420 | solid_root(color); |
| 1421 | } |
| 1422 | if (prev_str) { |
| 1423 | free(prev_str); |
| 1424 | } |
| 1425 | prev_str = strdup(solid_str); |
| 1426 | solid_on = 1; |
| 1427 | } |
| 1428 | |
| 1429 | |