/[rdesktop]/sourceforge.net/trunk/rdesktop/xwin.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/trunk/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1380 by astrand, Wed Jan 17 07:39:31 2007 UTC revision 1461 by astrand, Wed Mar 26 17:16:32 2008 UTC
# Line 2  Line 2 
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     User interface services - X Window System     User interface services - X Window System
4     Copyright (C) Matthew Chapman 1999-2007     Copyright (C) Matthew Chapman 1999-2007
5       Copyright 2007 Pierre Ossman <ossman@cendio.se> for Cendio AB
6    
7     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
# Line 74  typedef struct _seamless_window Line 75  typedef struct _seamless_window
75          int outpos_xoffset, outpos_yoffset;          int outpos_xoffset, outpos_yoffset;
76          int outpos_width, outpos_height;          int outpos_width, outpos_height;
77    
78            unsigned int icon_size;
79            unsigned int icon_offset;
80            char icon_buffer[32 * 32 * 4];
81    
82          struct _seamless_window *next;          struct _seamless_window *next;
83  } seamless_window;  } seamless_window;
84  static seamless_window *g_seamless_windows = NULL;  static seamless_window *g_seamless_windows = NULL;
# Line 81  static unsigned long g_seamless_focused Line 86  static unsigned long g_seamless_focused
86  static RD_BOOL g_seamless_started = False;      /* Server end is up and running */  static RD_BOOL g_seamless_started = False;      /* Server end is up and running */
87  static RD_BOOL g_seamless_active = False;       /* We are currently in seamless mode */  static RD_BOOL g_seamless_active = False;       /* We are currently in seamless mode */
88  static RD_BOOL g_seamless_hidden = False;       /* Desktop is hidden on server */  static RD_BOOL g_seamless_hidden = False;       /* Desktop is hidden on server */
89    static RD_BOOL g_seamless_broken_restack = False;       /* WM does not properly restack */
90  extern RD_BOOL g_seamless_rdp;  extern RD_BOOL g_seamless_rdp;
91    
92  extern uint32 g_embed_wnd;  extern uint32 g_embed_wnd;
# Line 102  static int g_bpp; Line 108  static int g_bpp;
108  static XIM g_IM;  static XIM g_IM;
109  static XIC g_IC;  static XIC g_IC;
110  static XModifierKeymap *g_mod_map;  static XModifierKeymap *g_mod_map;
111    /* Maps logical (xmodmap -pp) pointing device buttons (0-based) back
112       to physical (1-based) indices. */
113    static unsigned char g_pointer_log_to_phys_map[16];
114  static Cursor g_current_cursor;  static Cursor g_current_cursor;
115  static RD_HCURSOR g_null_cursor = NULL;  static RD_HCURSOR g_null_cursor = NULL;
116  static Atom g_protocol_atom, g_kill_atom;  static Atom g_protocol_atom, g_kill_atom;
# Line 521  mwm_hide_decorations(Window wnd) Line 530  mwm_hide_decorations(Window wnd)
530    
531  }  }
532    
533    typedef struct _sw_configurenotify_context
534    {
535            Window window;
536            unsigned long serial;
537    } sw_configurenotify_context;
538    
539    /* Predicate procedure for sw_wait_configurenotify */
540    static Bool
541    sw_configurenotify_p(Display * display, XEvent * xevent, XPointer arg)
542    {
543            sw_configurenotify_context *context = (sw_configurenotify_context *) arg;
544            if (xevent->xany.type == ConfigureNotify
545                && xevent->xconfigure.window == context->window
546                && xevent->xany.serial >= context->serial)
547                    return True;
548    
549            return False;
550    }
551    
552    /* Wait for a ConfigureNotify, with a equal or larger serial, on the
553       specified window. The event will be removed from the queue. We
554       could use XMaskEvent(StructureNotifyMask), but we would then risk
555       throwing away crucial events like DestroyNotify.
556    
557       After a ConfigureWindow, according to ICCCM section 4.1.5, we
558       should recieve a ConfigureNotify, either a real or synthetic
559       one. This indicates that the configure has been "completed".
560       However, some WMs such as several versions of Metacity fails to
561       send synthetic events. See bug
562       http://bugzilla.gnome.org/show_bug.cgi?id=322840. We need to use a
563       timeout to avoid a hang. Tk uses the same approach. */
564    static void
565    sw_wait_configurenotify(Window wnd, unsigned long serial)
566    {
567            XEvent xevent;
568            sw_configurenotify_context context;
569            struct timeval now;
570            struct timeval nextsecond;
571            RD_BOOL got = False;
572    
573            context.window = wnd;
574            context.serial = serial;
575    
576            gettimeofday(&nextsecond, NULL);
577            nextsecond.tv_sec += 1;
578    
579            do
580            {
581                    if (XCheckIfEvent(g_display, &xevent, sw_configurenotify_p, (XPointer) & context))
582                    {
583                            got = True;
584                            break;
585                    }
586                    usleep(100000);
587                    gettimeofday(&now, NULL);
588            }
589            while (timercmp(&now, &nextsecond, <));
590    
591            if (!got)
592            {
593                    warning("Broken Window Manager: Timeout while waiting for ConfigureNotify\n");
594            }
595    }
596    
597    /* Get the toplevel window, in case of reparenting */
598    static Window
599    sw_get_toplevel(Window wnd)
600    {
601            Window root, parent;
602            Window *child_list;
603            unsigned int num_children;
604    
605            while (1)
606            {
607                    XQueryTree(g_display, wnd, &root, &parent, &child_list, &num_children);
608                    if (root == parent)
609                    {
610                            break;
611                    }
612                    else if (!parent)
613                    {
614                            warning("Internal error: sw_get_toplevel called with root window\n");
615                    }
616    
617                    wnd = parent;
618            }
619    
620            return wnd;
621    }
622    
623    
624    /* Check if wnd is already behind a window wrt stacking order */
625    static RD_BOOL
626    sw_window_is_behind(Window wnd, Window behind)
627    {
628            Window dummy1, dummy2;
629            Window *child_list;
630            unsigned int num_children;
631            unsigned int i;
632            RD_BOOL found_behind = False;
633            RD_BOOL found_wnd = False;
634    
635            wnd = sw_get_toplevel(wnd);
636            behind = sw_get_toplevel(behind);
637    
638            XQueryTree(g_display, RootWindowOfScreen(g_screen), &dummy1, &dummy2, &child_list,
639                       &num_children);
640    
641            for (i = num_children - 1; i >= 0; i--)
642            {
643                    if (child_list[i] == behind)
644                    {
645                            found_behind = True;
646                    }
647                    else if (child_list[i] == wnd)
648                    {
649                            found_wnd = True;
650                            break;
651                    }
652            }
653    
654            if (child_list)
655                    XFree(child_list);
656    
657            if (!found_wnd)
658            {
659                    warning("sw_window_is_behind: Unable to find window 0x%lx\n", wnd);
660    
661                    if (!found_behind)
662                    {
663                            warning("sw_window_is_behind: Unable to find behind window 0x%lx\n",
664                                    behind);
665                    }
666            }
667    
668            return found_behind;
669    }
670    
671    
672    /* Test if the window manager correctly handles window restacking. In
673       particular, we are testing if it's possible to place a window
674       between two other windows. Many WMs such as Metacity can only stack
675       windows on the top or bottom. The window creation should mostly
676       match ui_seamless_create_window. */
677    static void
678    seamless_restack_test()
679    {
680            /* The goal is to have the middle window between top and
681               bottom.  The middle window is initially at the top,
682               though. */
683            Window wnds[3];         /* top, middle and bottom */
684            int i;
685            XEvent xevent;
686            XWindowChanges values;
687            unsigned long restack_serial;
688    
689            for (i = 0; i < 3; i++)
690            {
691                    char name[64];
692                    wnds[i] =
693                            XCreateSimpleWindow(g_display, RootWindowOfScreen(g_screen), 0, 0, 20, 20,
694                                                0, 0, 0);
695                    snprintf(name, sizeof(name), "SeamlessRDP restack test - window %d", i);
696                    XStoreName(g_display, wnds[i], name);
697                    ewmh_set_wm_name(wnds[i], name);
698    
699                    /* Hide decorations. Often this means that no
700                       reparenting will be done, which makes the restack
701                       easier. Besides, we want to mimic our other
702                       seamless windows as much as possible. We must still
703                       handle the case with reparenting, though. */
704                    mwm_hide_decorations(wnds[i]);
705    
706                    /* Prevent windows from appearing in task bar */
707                    XSetTransientForHint(g_display, wnds[i], RootWindowOfScreen(g_screen));
708                    ewmh_set_window_popup(wnds[i]);
709    
710                    /* We need to catch MapNotify/ConfigureNotify */
711                    XSelectInput(g_display, wnds[i], StructureNotifyMask);
712            }
713    
714            /* Map Windows. Currently, we assume that XMapRaised places
715               the window on the top of the stack. Should be fairly safe;
716               the window is configured before it's mapped. */
717            XMapRaised(g_display, wnds[2]); /* bottom */
718            do
719            {
720                    XWindowEvent(g_display, wnds[2], StructureNotifyMask, &xevent);
721            }
722            while (xevent.type != MapNotify);
723            XMapRaised(g_display, wnds[0]); /* top */
724            do
725            {
726                    XWindowEvent(g_display, wnds[0], StructureNotifyMask, &xevent);
727            }
728            while (xevent.type != MapNotify);
729            XMapRaised(g_display, wnds[1]); /* middle */
730            do
731            {
732                    XWindowEvent(g_display, wnds[1], StructureNotifyMask, &xevent);
733            }
734            while (xevent.type != MapNotify);
735    
736            /* The stacking order should now be 1 - 0 - 2 */
737            if (!sw_window_is_behind(wnds[0], wnds[1]) || !sw_window_is_behind(wnds[2], wnds[1]))
738            {
739                    /* Ok, technically a WM is allowed to stack windows arbitrarily, but... */
740                    warning("Broken Window Manager: Unable to test window restacking\n");
741                    g_seamless_broken_restack = True;
742                    for (i = 0; i < 3; i++)
743                            XDestroyWindow(g_display, wnds[i]);
744                    return;
745            }
746    
747            /* Restack, using XReconfigureWMWindow, which should correctly
748               handle reparented windows as well as nonreparenting WMs. */
749            values.stack_mode = Below;
750            values.sibling = wnds[0];
751            restack_serial = XNextRequest(g_display);
752            XReconfigureWMWindow(g_display, wnds[1], DefaultScreen(g_display), CWStackMode | CWSibling,
753                                 &values);
754            sw_wait_configurenotify(wnds[1], restack_serial);
755    
756            /* Now verify that middle is behind top but not behind
757               bottom */
758            if (!sw_window_is_behind(wnds[1], wnds[0]))
759            {
760                    warning("Broken Window Manager: doesn't handle restack (restack request was ignored)\n");
761                    g_seamless_broken_restack = True;
762            }
763            else if (sw_window_is_behind(wnds[1], wnds[2]))
764            {
765                    warning("Broken Window Manager: doesn't handle restack (window was moved to bottom)\n");
766                    g_seamless_broken_restack = True;
767            }
768    
769            /* Destroy windows */
770            for (i = 0; i < 3; i++)
771                    XDestroyWindow(g_display, wnds[i]);
772    }
773    
774  #define SPLITCOLOUR15(colour, rv) \  #define SPLITCOLOUR15(colour, rv) \
775  { \  { \
776          rv.red = ((colour >> 7) & 0xf8) | ((colour >> 12) & 0x7); \          rv.red = ((colour >> 7) & 0xf8) | ((colour >> 12) & 0x7); \
# Line 575  translate_colour(uint32 colour) Line 825  translate_colour(uint32 colour)
825                          SPLITCOLOUR16(colour, pc);                          SPLITCOLOUR16(colour, pc);
826                          break;                          break;
827                  case 24:                  case 24:
828                    case 32:
829                          SPLITCOLOUR24(colour, pc);                          SPLITCOLOUR24(colour, pc);
830                          break;                          break;
831                  default:                  default:
# Line 1183  translate_image(int width, int height, u Line 1434  translate_image(int width, int height, u
1434             is only set for compatible depths, but the RDP depth might've             is only set for compatible depths, but the RDP depth might've
1435             changed during connection negotiations.             changed during connection negotiations.
1436           */           */
1437    
1438            /* todo */
1439            if (g_server_depth == 32 && g_depth == 24)
1440            {
1441                    return data;
1442            }
1443    
1444          if (g_no_translate_image)          if (g_no_translate_image)
1445          {          {
1446                  if ((g_depth == 15 && g_server_depth == 15) ||                  if ((g_depth == 15 && g_server_depth == 15) ||
# Line 1260  translate_image(int width, int height, u Line 1518  translate_image(int width, int height, u
1518          return out;          return out;
1519  }  }
1520    
1521    static void
1522    xwin_refresh_pointer_map(void)
1523    {
1524            unsigned char phys_to_log_map[sizeof(g_pointer_log_to_phys_map)];
1525            int i, pointer_buttons;
1526    
1527            pointer_buttons = XGetPointerMapping(g_display, phys_to_log_map, sizeof(phys_to_log_map));
1528            for (i = 0; i < pointer_buttons; ++i)
1529            {
1530                    /* This might produce multiple logical buttons mapping
1531                       to a single physical one, but hey, that's
1532                       life... */
1533                    g_pointer_log_to_phys_map[phys_to_log_map[i] - 1] = i + 1;
1534            }
1535    }
1536    
1537  RD_BOOL  RD_BOOL
1538  get_key_state(unsigned int state, uint32 keysym)  get_key_state(unsigned int state, uint32 keysym)
1539  {  {
# Line 1504  select_visual(int screen_num) Line 1778  select_visual(int screen_num)
1778  }  }
1779    
1780  static XErrorHandler g_old_error_handler;  static XErrorHandler g_old_error_handler;
1781    static RD_BOOL g_error_expected = False;
1782    
1783    /* Check if the X11 window corresponding to a seamless window with
1784       specified id exists. */
1785    RD_BOOL
1786    sw_window_exists(unsigned long id)
1787    {
1788            seamless_window *sw;
1789            char *name;
1790            Status sts = 0;
1791    
1792            sw = sw_get_window_by_id(id);
1793            if (!sw)
1794                    return False;
1795    
1796            g_error_expected = True;
1797            sts = XFetchName(g_display, sw->wnd, &name);
1798            g_error_expected = False;
1799            if (sts)
1800            {
1801                    XFree(name);
1802            }
1803    
1804            return sts;
1805    }
1806    
1807  static int  static int
1808  error_handler(Display * dpy, XErrorEvent * eev)  error_handler(Display * dpy, XErrorEvent * eev)
1809  {  {
1810          if ((eev->error_code == BadMatch) && (eev->request_code == X_ConfigureWindow))          if (g_error_expected)
         {  
                 fprintf(stderr, "Got \"BadMatch\" when trying to restack windows.\n");  
                 fprintf(stderr,  
                         "This is most likely caused by a broken window manager (commonly KWin).\n");  
1811                  return 0;                  return 0;
         }  
1812    
1813          return g_old_error_handler(dpy, eev);          return g_old_error_handler(dpy, eev);
1814  }  }
# Line 1614  ui_init(void) Line 1908  ui_init(void)
1908          g_width = (g_width + 3) & ~3;          g_width = (g_width + 3) & ~3;
1909    
1910          g_mod_map = XGetModifierMapping(g_display);          g_mod_map = XGetModifierMapping(g_display);
1911            xwin_refresh_pointer_map();
1912    
1913          xkeymap_init();          xkeymap_init();
1914    
# Line 1623  ui_init(void) Line 1918  ui_init(void)
1918          xclip_init();          xclip_init();
1919          ewmh_init();          ewmh_init();
1920          if (g_seamless_rdp)          if (g_seamless_rdp)
1921            {
1922                    seamless_restack_test();
1923                  seamless_init();                  seamless_init();
1924            }
1925    
1926          DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", g_server_depth, g_bpp, g_depth));          DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", g_server_depth, g_bpp, g_depth));
1927    
# Line 1877  handle_button_event(XEvent xevent, RD_BO Line 2175  handle_button_event(XEvent xevent, RD_BO
2175  {  {
2176          uint16 button, flags = 0;          uint16 button, flags = 0;
2177          g_last_gesturetime = xevent.xbutton.time;          g_last_gesturetime = xevent.xbutton.time;
2178            /* Reverse the pointer button mapping, e.g. in the case of
2179               "left-handed mouse mode"; the RDP session expects to
2180               receive physical buttons (true in mstsc as well) and
2181               logical button behavior depends on the remote desktop's own
2182               mouse settings */
2183            xevent.xbutton.button = g_pointer_log_to_phys_map[xevent.xbutton.button - 1];
2184          button = xkeymap_translate_button(xevent.xbutton.button);          button = xkeymap_translate_button(xevent.xbutton.button);
2185          if (button == 0)          if (button == 0)
2186                  return;                  return;
# Line 1989  xwin_process_events(void) Line 2293  xwin_process_events(void)
2293                                  /* the window manager told us to quit */                                  /* the window manager told us to quit */
2294                                  if ((xevent.xclient.message_type == g_protocol_atom)                                  if ((xevent.xclient.message_type == g_protocol_atom)
2295                                      && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))                                      && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
2296                                          /* Quit */                                  {
2297                                          return 0;                                          /* When killing a seamless window, close the window on the
2298                                               serverside instead of terminating rdesktop */
2299                                            sw = sw_get_window_by_wnd(xevent.xclient.window);
2300                                            if (!sw)
2301                                                    /* Otherwise, quit */
2302                                                    return 0;
2303                                            /* send seamless destroy process message */
2304                                            seamless_send_destroy(sw->id);
2305                                    }
2306                                  break;                                  break;
2307    
2308                          case KeyPress:                          case KeyPress:
# Line 2091  xwin_process_events(void) Line 2403  xwin_process_events(void)
2403                                  if (!sw)                                  if (!sw)
2404                                          break;                                          break;
2405    
2406                                    /* Menu windows are real X11 windows,
2407                                       with focus. When such a window is
2408                                       destroyed, focus is reverted to the
2409                                       main application window, which
2410                                       would cause us to send FOCUS. This
2411                                       breaks window switching in, say,
2412                                       Seamonkey. We shouldn't need to
2413                                       send FOCUS: Windows should also
2414                                       revert focus to some other window
2415                                       when the menu window is
2416                                       destroyed. So, we only send FOCUS
2417                                       if the previous focus window still
2418                                       exists. */
2419                                  if (sw->id != g_seamless_focused)                                  if (sw->id != g_seamless_focused)
2420                                  {                                  {
2421                                          seamless_send_focus(sw->id, 0);  
2422                                            if (sw_window_exists(g_seamless_focused))
2423                                                    seamless_send_focus(sw->id, 0);
2424                                          g_seamless_focused = sw->id;                                          g_seamless_focused = sw->id;
2425                                  }                                  }
2426                                  break;                                  break;
# Line 2164  xwin_process_events(void) Line 2491  xwin_process_events(void)
2491                                          XFreeModifiermap(g_mod_map);                                          XFreeModifiermap(g_mod_map);
2492                                          g_mod_map = XGetModifierMapping(g_display);                                          g_mod_map = XGetModifierMapping(g_display);
2493                                  }                                  }
2494    
2495                                    if (xevent.xmapping.request == MappingPointer)
2496                                    {
2497                                            xwin_refresh_pointer_map();
2498                                    }
2499    
2500                                  break;                                  break;
2501    
2502                                  /* clipboard stuff */                                  /* clipboard stuff */
# Line 3218  ui_desktop_restore(uint32 offset, int x, Line 3551  ui_desktop_restore(uint32 offset, int x,
3551                  return;                  return;
3552    
3553          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
3554                               (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8);                               (char *) data, cx, cy, g_bpp, 0);
3555    
3556          if (g_ownbackstore)          if (g_ownbackstore)
3557          {          {
# Line 3407  ui_seamless_create_window(unsigned long Line 3740  ui_seamless_create_window(unsigned long
3740                  ewmh_set_window_modal(wnd);                  ewmh_set_window_modal(wnd);
3741          }          }
3742    
3743            if (flags & SEAMLESSRDP_CREATE_TOPMOST)
3744            {
3745                    /* Make window always-on-top */
3746                    ewmh_set_window_above(wnd);
3747            }
3748    
3749          /* FIXME: Support for Input Context:s */          /* FIXME: Support for Input Context:s */
3750    
3751          get_input_mask(&input_mask);          get_input_mask(&input_mask);
# Line 3414  ui_seamless_create_window(unsigned long Line 3753  ui_seamless_create_window(unsigned long
3753    
3754          XSelectInput(g_display, wnd, input_mask);          XSelectInput(g_display, wnd, input_mask);
3755    
3756          /* handle the WM_DELETE_WINDOW protocol. FIXME: When killing a          /* handle the WM_DELETE_WINDOW protocol. */
            seamless window, we could try to close the window on the  
            serverside, instead of terminating rdesktop */  
3757          XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);          XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);
3758    
3759          sw = xmalloc(sizeof(seamless_window));          sw = xmalloc(sizeof(seamless_window));
3760    
3761            memset(sw, 0, sizeof(seamless_window));
3762    
3763          sw->wnd = wnd;          sw->wnd = wnd;
3764          sw->id = id;          sw->id = id;
         sw->behind = 0;  
3765          sw->group = sw_find_group(group, False);          sw->group = sw_find_group(group, False);
3766          sw->group->refcnt++;          sw->group->refcnt++;
         sw->xoffset = 0;  
         sw->yoffset = 0;  
         sw->width = 0;  
         sw->height = 0;  
3767          sw->state = SEAMLESSRDP_NOTYETMAPPED;          sw->state = SEAMLESSRDP_NOTYETMAPPED;
3768          sw->desktop = 0;          sw->desktop = 0;
3769          sw->position_timer = xmalloc(sizeof(struct timeval));          sw->position_timer = xmalloc(sizeof(struct timeval));
# Line 3496  ui_seamless_destroy_group(unsigned long Line 3831  ui_seamless_destroy_group(unsigned long
3831    
3832    
3833  void  void
3834    ui_seamless_seticon(unsigned long id, const char *format, int width, int height, int chunk,
3835                        const char *data, int chunk_len)
3836    {
3837            seamless_window *sw;
3838    
3839            if (!g_seamless_active)
3840                    return;
3841    
3842            sw = sw_get_window_by_id(id);
3843            if (!sw)
3844            {
3845                    warning("ui_seamless_seticon: No information for window 0x%lx\n", id);
3846                    return;
3847            }
3848    
3849            if (chunk == 0)
3850            {
3851                    if (sw->icon_size)
3852                            warning("ui_seamless_seticon: New icon started before previous completed\n");
3853    
3854                    if (strcmp(format, "RGBA") != 0)
3855                    {
3856                            warning("ui_seamless_seticon: Uknown icon format \"%s\"\n", format);
3857                            return;
3858                    }
3859    
3860                    sw->icon_size = width * height * 4;
3861                    if (sw->icon_size > 32 * 32 * 4)
3862                    {
3863                            warning("ui_seamless_seticon: Icon too large (%d bytes)\n", sw->icon_size);
3864                            sw->icon_size = 0;
3865                            return;
3866                    }
3867    
3868                    sw->icon_offset = 0;
3869            }
3870            else
3871            {
3872                    if (!sw->icon_size)
3873                            return;
3874            }
3875    
3876            if (chunk_len > (sw->icon_size - sw->icon_offset))
3877            {
3878                    warning("ui_seamless_seticon: Too large chunk received (%d bytes > %d bytes)\n",
3879                            chunk_len, sw->icon_size - sw->icon_offset);
3880                    sw->icon_size = 0;
3881                    return;
3882            }
3883    
3884            memcpy(sw->icon_buffer + sw->icon_offset, data, chunk_len);
3885            sw->icon_offset += chunk_len;
3886    
3887            if (sw->icon_offset == sw->icon_size)
3888            {
3889                    ewmh_set_icon(sw->wnd, width, height, sw->icon_buffer);
3890                    sw->icon_size = 0;
3891            }
3892    }
3893    
3894    
3895    void
3896    ui_seamless_delicon(unsigned long id, const char *format, int width, int height)
3897    {
3898            seamless_window *sw;
3899    
3900            if (!g_seamless_active)
3901                    return;
3902    
3903            sw = sw_get_window_by_id(id);
3904            if (!sw)
3905            {
3906                    warning("ui_seamless_seticon: No information for window 0x%lx\n", id);
3907                    return;
3908            }
3909    
3910            if (strcmp(format, "RGBA") != 0)
3911            {
3912                    warning("ui_seamless_seticon: Uknown icon format \"%s\"\n", format);
3913                    return;
3914            }
3915    
3916            ewmh_del_icon(sw->wnd, width, height);
3917    }
3918    
3919    
3920    void
3921  ui_seamless_move_window(unsigned long id, int x, int y, int width, int height, unsigned long flags)  ui_seamless_move_window(unsigned long id, int x, int y, int width, int height, unsigned long flags)
3922  {  {
3923          seamless_window *sw;          seamless_window *sw;
# Line 3541  void Line 3963  void
3963  ui_seamless_restack_window(unsigned long id, unsigned long behind, unsigned long flags)  ui_seamless_restack_window(unsigned long id, unsigned long behind, unsigned long flags)
3964  {  {
3965          seamless_window *sw;          seamless_window *sw;
3966            XWindowChanges values;
3967            unsigned long restack_serial;
3968    
3969          if (!g_seamless_active)          if (!g_seamless_active)
3970                  return;                  return;
# Line 3555  ui_seamless_restack_window(unsigned long Line 3979  ui_seamless_restack_window(unsigned long
3979          if (behind)          if (behind)
3980          {          {
3981                  seamless_window *sw_behind;                  seamless_window *sw_behind;
                 Window wnds[2];  
3982    
3983                  sw_behind = sw_get_window_by_id(behind);                  sw_behind = sw_get_window_by_id(behind);
3984                  if (!sw_behind)                  if (!sw_behind)
3985                  {                  {
3986                          warning("ui_seamless_restack_window: No information for window 0x%lx\n",                          warning("ui_seamless_restack_window: No information for behind window 0x%lx\n", behind);
                                 behind);  
3987                          return;                          return;
3988                  }                  }
3989    
3990                  wnds[1] = sw_behind->wnd;                  if (!g_seamless_broken_restack)
3991                  wnds[0] = sw->wnd;                  {
3992                            values.stack_mode = Below;
3993                  XRestackWindows(g_display, wnds, 2);                          values.sibling = sw_behind->wnd;
3994                            restack_serial = XNextRequest(g_display);
3995                            XReconfigureWMWindow(g_display, sw->wnd, DefaultScreen(g_display),
3996                                                 CWStackMode | CWSibling, &values);
3997                            sw_wait_configurenotify(sw->wnd, restack_serial);
3998                    }
3999          }          }
4000          else          else
4001          {          {
4002                  XRaiseWindow(g_display, sw->wnd);                  values.stack_mode = Above;
4003                    restack_serial = XNextRequest(g_display);
4004                    XReconfigureWMWindow(g_display, sw->wnd, DefaultScreen(g_display), CWStackMode,
4005                                         &values);
4006                    sw_wait_configurenotify(sw->wnd, restack_serial);
4007          }          }
4008    
4009          sw_restack_window(sw, behind);          sw_restack_window(sw, behind);
4010    
4011            if (flags & SEAMLESSRDP_CREATE_TOPMOST)
4012            {
4013                    /* Make window always-on-top */
4014                    ewmh_set_window_above(sw->wnd);
4015            }
4016  }  }
4017    
4018    

Legend:
Removed from v.1380  
changed lines
  Added in v.1461

  ViewVC Help
Powered by ViewVC 1.1.26