/[rdesktop]/jpeg/rdesktop/trunk/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 /jpeg/rdesktop/trunk/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 1459 by astrand, Wed Mar 26 16:44:55 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            time_t start;
570            RD_BOOL got = False;
571    
572            context.window = wnd;
573            context.serial = serial;
574            start = time(NULL);
575    
576            do
577            {
578                    if (XCheckIfEvent(g_display, &xevent, sw_configurenotify_p, (XPointer) & context))
579                    {
580                            got = True;
581                            break;
582                    }
583                    usleep(100000);
584            }
585            while (time(NULL) - start < 2);
586    
587            if (!got)
588            {
589                    warning("Broken Window Manager: Timeout while waiting for ConfigureNotify\n");
590            }
591    }
592    
593    /* Get the toplevel window, in case of reparenting */
594    static Window
595    sw_get_toplevel(Window wnd)
596    {
597            Window root, parent;
598            Window *child_list;
599            unsigned int num_children;
600    
601            while (1)
602            {
603                    XQueryTree(g_display, wnd, &root, &parent, &child_list, &num_children);
604                    if (root == parent)
605                    {
606                            break;
607                    }
608                    else if (!parent)
609                    {
610                            warning("Internal error: sw_get_toplevel called with root window\n");
611                    }
612    
613                    wnd = parent;
614            }
615    
616            return wnd;
617    }
618    
619    
620    /* Check if wnd is already behind a window wrt stacking order */
621    static RD_BOOL
622    sw_window_is_behind(Window wnd, Window behind)
623    {
624            Window dummy1, dummy2;
625            Window *child_list;
626            unsigned int num_children;
627            unsigned int i;
628            RD_BOOL found_behind = False;
629            RD_BOOL found_wnd = False;
630    
631            wnd = sw_get_toplevel(wnd);
632            behind = sw_get_toplevel(behind);
633    
634            XQueryTree(g_display, RootWindowOfScreen(g_screen), &dummy1, &dummy2, &child_list,
635                       &num_children);
636    
637            for (i = num_children - 1; i >= 0; i--)
638            {
639                    if (child_list[i] == behind)
640                    {
641                            found_behind = True;
642                    }
643                    else if (child_list[i] == wnd)
644                    {
645                            found_wnd = True;
646                            break;
647                    }
648            }
649    
650            if (child_list)
651                    XFree(child_list);
652    
653            if (!found_wnd)
654            {
655                    warning("sw_window_is_behind: Unable to find window 0x%lx\n", wnd);
656    
657                    if (!found_behind)
658                    {
659                            warning("sw_window_is_behind: Unable to find behind window 0x%lx\n",
660                                    behind);
661                    }
662            }
663    
664            return found_behind;
665    }
666    
667    
668    /* Test if the window manager correctly handles window restacking. In
669       particular, we are testing if it's possible to place a window
670       between two other windows. Many WMs such as Metacity can only stack
671       windows on the top or bottom. The window creation should mostly
672       match ui_seamless_create_window. */
673    static void
674    seamless_restack_test()
675    {
676            /* The goal is to have the middle window between top and
677               bottom.  The middle window is initially at the top,
678               though. */
679            Window wnds[3];         /* top, middle and bottom */
680            int i;
681            XEvent xevent;
682            XWindowChanges values;
683            unsigned long restack_serial;
684    
685            for (i = 0; i < 3; i++)
686            {
687                    char name[64];
688                    wnds[i] =
689                            XCreateSimpleWindow(g_display, RootWindowOfScreen(g_screen), 0, 0, 20, 20,
690                                                0, 0, 0);
691                    snprintf(name, sizeof(name), "SeamlessRDP restack test - window %d", i);
692                    XStoreName(g_display, wnds[i], name);
693                    ewmh_set_wm_name(wnds[i], name);
694    
695                    /* Hide decorations. Often this means that no
696                       reparenting will be done, which makes the restack
697                       easier. Besides, we want to mimic our other
698                       seamless windows as much as possible. We must still
699                       handle the case with reparenting, though. */
700                    mwm_hide_decorations(wnds[i]);
701    
702                    /* Prevent windows from appearing in task bar */
703                    XSetTransientForHint(g_display, wnds[i], RootWindowOfScreen(g_screen));
704                    ewmh_set_window_popup(wnds[i]);
705    
706                    /* We need to catch MapNotify/ConfigureNotify */
707                    XSelectInput(g_display, wnds[i], StructureNotifyMask);
708            }
709    
710            /* Map Windows. Currently, we assume that XMapRaised places
711               the window on the top of the stack. Should be fairly safe;
712               the window is configured before it's mapped. */
713            XMapRaised(g_display, wnds[2]); /* bottom */
714            do
715            {
716                    XWindowEvent(g_display, wnds[2], StructureNotifyMask, &xevent);
717            }
718            while (xevent.type != MapNotify);
719            XMapRaised(g_display, wnds[0]); /* top */
720            do
721            {
722                    XWindowEvent(g_display, wnds[0], StructureNotifyMask, &xevent);
723            }
724            while (xevent.type != MapNotify);
725            XMapRaised(g_display, wnds[1]); /* middle */
726            do
727            {
728                    XWindowEvent(g_display, wnds[1], StructureNotifyMask, &xevent);
729            }
730            while (xevent.type != MapNotify);
731    
732            /* The stacking order should now be 1 - 0 - 2 */
733            if (!sw_window_is_behind(wnds[0], wnds[1]) || !sw_window_is_behind(wnds[2], wnds[1]))
734            {
735                    /* Ok, technically a WM is allowed to stack windows arbitrarily, but... */
736                    warning("Broken Window Manager: Unable to test window restacking\n");
737                    g_seamless_broken_restack = True;
738                    for (i = 0; i < 3; i++)
739                            XDestroyWindow(g_display, wnds[i]);
740                    return;
741            }
742    
743            /* Restack, using XReconfigureWMWindow, which should correctly
744               handle reparented windows as well as nonreparenting WMs. */
745            values.stack_mode = Below;
746            values.sibling = wnds[0];
747            restack_serial = XNextRequest(g_display);
748            XReconfigureWMWindow(g_display, wnds[1], DefaultScreen(g_display), CWStackMode | CWSibling,
749                                 &values);
750            sw_wait_configurenotify(wnds[1], restack_serial);
751    
752            /* Now verify that middle is behind top but not behind
753               bottom */
754            if (!sw_window_is_behind(wnds[1], wnds[0]))
755            {
756                    warning("Broken Window Manager: doesn't handle restack (restack request was ignored)\n");
757                    g_seamless_broken_restack = True;
758            }
759            else if (sw_window_is_behind(wnds[1], wnds[2]))
760            {
761                    warning("Broken Window Manager: doesn't handle restack (window was moved to bottom)\n");
762                    g_seamless_broken_restack = True;
763            }
764    
765            /* Destroy windows */
766            for (i = 0; i < 3; i++)
767                    XDestroyWindow(g_display, wnds[i]);
768    }
769    
770  #define SPLITCOLOUR15(colour, rv) \  #define SPLITCOLOUR15(colour, rv) \
771  { \  { \
772          rv.red = ((colour >> 7) & 0xf8) | ((colour >> 12) & 0x7); \          rv.red = ((colour >> 7) & 0xf8) | ((colour >> 12) & 0x7); \
# Line 575  translate_colour(uint32 colour) Line 821  translate_colour(uint32 colour)
821                          SPLITCOLOUR16(colour, pc);                          SPLITCOLOUR16(colour, pc);
822                          break;                          break;
823                  case 24:                  case 24:
824                    case 32:
825                          SPLITCOLOUR24(colour, pc);                          SPLITCOLOUR24(colour, pc);
826                          break;                          break;
827                  default:                  default:
# Line 1183  translate_image(int width, int height, u Line 1430  translate_image(int width, int height, u
1430             is only set for compatible depths, but the RDP depth might've             is only set for compatible depths, but the RDP depth might've
1431             changed during connection negotiations.             changed during connection negotiations.
1432           */           */
1433    
1434            /* todo */
1435            if (g_server_depth == 32 && g_depth == 24)
1436            {
1437                    return data;
1438            }
1439    
1440          if (g_no_translate_image)          if (g_no_translate_image)
1441          {          {
1442                  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 1514  translate_image(int width, int height, u
1514          return out;          return out;
1515  }  }
1516    
1517    static void
1518    xwin_refresh_pointer_map(void)
1519    {
1520            unsigned char phys_to_log_map[sizeof(g_pointer_log_to_phys_map)];
1521            int i, pointer_buttons;
1522    
1523            pointer_buttons = XGetPointerMapping(g_display, phys_to_log_map, sizeof(phys_to_log_map));
1524            for (i = 0; i < pointer_buttons; ++i)
1525            {
1526                    /* This might produce multiple logical buttons mapping
1527                       to a single physical one, but hey, that's
1528                       life... */
1529                    g_pointer_log_to_phys_map[phys_to_log_map[i] - 1] = i + 1;
1530            }
1531    }
1532    
1533  RD_BOOL  RD_BOOL
1534  get_key_state(unsigned int state, uint32 keysym)  get_key_state(unsigned int state, uint32 keysym)
1535  {  {
# Line 1504  select_visual(int screen_num) Line 1774  select_visual(int screen_num)
1774  }  }
1775    
1776  static XErrorHandler g_old_error_handler;  static XErrorHandler g_old_error_handler;
1777    static RD_BOOL g_error_expected = False;
1778    
1779    /* Check if the X11 window corresponding to a seamless window with
1780       specified id exists. */
1781    RD_BOOL
1782    sw_window_exists(unsigned long id)
1783    {
1784            seamless_window *sw;
1785            char *name;
1786            Status sts = 0;
1787    
1788            sw = sw_get_window_by_id(id);
1789            if (!sw)
1790                    return False;
1791    
1792            g_error_expected = True;
1793            sts = XFetchName(g_display, sw->wnd, &name);
1794            g_error_expected = False;
1795            if (sts)
1796            {
1797                    XFree(name);
1798            }
1799    
1800            return sts;
1801    }
1802    
1803  static int  static int
1804  error_handler(Display * dpy, XErrorEvent * eev)  error_handler(Display * dpy, XErrorEvent * eev)
1805  {  {
1806          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");  
1807                  return 0;                  return 0;
         }  
1808    
1809          return g_old_error_handler(dpy, eev);          return g_old_error_handler(dpy, eev);
1810  }  }
# Line 1614  ui_init(void) Line 1904  ui_init(void)
1904          g_width = (g_width + 3) & ~3;          g_width = (g_width + 3) & ~3;
1905    
1906          g_mod_map = XGetModifierMapping(g_display);          g_mod_map = XGetModifierMapping(g_display);
1907            xwin_refresh_pointer_map();
1908    
1909          xkeymap_init();          xkeymap_init();
1910    
# Line 1623  ui_init(void) Line 1914  ui_init(void)
1914          xclip_init();          xclip_init();
1915          ewmh_init();          ewmh_init();
1916          if (g_seamless_rdp)          if (g_seamless_rdp)
1917            {
1918                    seamless_restack_test();
1919                  seamless_init();                  seamless_init();
1920            }
1921    
1922          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));
1923    
# Line 1877  handle_button_event(XEvent xevent, RD_BO Line 2171  handle_button_event(XEvent xevent, RD_BO
2171  {  {
2172          uint16 button, flags = 0;          uint16 button, flags = 0;
2173          g_last_gesturetime = xevent.xbutton.time;          g_last_gesturetime = xevent.xbutton.time;
2174            /* Reverse the pointer button mapping, e.g. in the case of
2175               "left-handed mouse mode"; the RDP session expects to
2176               receive physical buttons (true in mstsc as well) and
2177               logical button behavior depends on the remote desktop's own
2178               mouse settings */
2179            xevent.xbutton.button = g_pointer_log_to_phys_map[xevent.xbutton.button - 1];
2180          button = xkeymap_translate_button(xevent.xbutton.button);          button = xkeymap_translate_button(xevent.xbutton.button);
2181          if (button == 0)          if (button == 0)
2182                  return;                  return;
# Line 1989  xwin_process_events(void) Line 2289  xwin_process_events(void)
2289                                  /* the window manager told us to quit */                                  /* the window manager told us to quit */
2290                                  if ((xevent.xclient.message_type == g_protocol_atom)                                  if ((xevent.xclient.message_type == g_protocol_atom)
2291                                      && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))                                      && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
2292                                          /* Quit */                                  {
2293                                          return 0;                                          /* When killing a seamless window, close the window on the
2294                                               serverside instead of terminating rdesktop */
2295                                            sw = sw_get_window_by_wnd(xevent.xclient.window);
2296                                            if (!sw)
2297                                                    /* Otherwise, quit */
2298                                                    return 0;
2299                                            /* send seamless destroy process message */
2300                                            seamless_send_destroy(sw->id);
2301                                    }
2302                                  break;                                  break;
2303    
2304                          case KeyPress:                          case KeyPress:
# Line 2091  xwin_process_events(void) Line 2399  xwin_process_events(void)
2399                                  if (!sw)                                  if (!sw)
2400                                          break;                                          break;
2401    
2402                                    /* Menu windows are real X11 windows,
2403                                       with focus. When such a window is
2404                                       destroyed, focus is reverted to the
2405                                       main application window, which
2406                                       would cause us to send FOCUS. This
2407                                       breaks window switching in, say,
2408                                       Seamonkey. We shouldn't need to
2409                                       send FOCUS: Windows should also
2410                                       revert focus to some other window
2411                                       when the menu window is
2412                                       destroyed. So, we only send FOCUS
2413                                       if the previous focus window still
2414                                       exists. */
2415                                  if (sw->id != g_seamless_focused)                                  if (sw->id != g_seamless_focused)
2416                                  {                                  {
2417                                          seamless_send_focus(sw->id, 0);  
2418                                            if (sw_window_exists(g_seamless_focused))
2419                                                    seamless_send_focus(sw->id, 0);
2420                                          g_seamless_focused = sw->id;                                          g_seamless_focused = sw->id;
2421                                  }                                  }
2422                                  break;                                  break;
# Line 2164  xwin_process_events(void) Line 2487  xwin_process_events(void)
2487                                          XFreeModifiermap(g_mod_map);                                          XFreeModifiermap(g_mod_map);
2488                                          g_mod_map = XGetModifierMapping(g_display);                                          g_mod_map = XGetModifierMapping(g_display);
2489                                  }                                  }
2490    
2491                                    if (xevent.xmapping.request == MappingPointer)
2492                                    {
2493                                            xwin_refresh_pointer_map();
2494                                    }
2495    
2496                                  break;                                  break;
2497    
2498                                  /* clipboard stuff */                                  /* clipboard stuff */
# Line 3218  ui_desktop_restore(uint32 offset, int x, Line 3547  ui_desktop_restore(uint32 offset, int x,
3547                  return;                  return;
3548    
3549          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,          image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
3550                               (char *) data, cx, cy, BitmapPad(g_display), cx * g_bpp / 8);                               (char *) data, cx, cy, g_bpp, 0);
3551    
3552          if (g_ownbackstore)          if (g_ownbackstore)
3553          {          {
# Line 3407  ui_seamless_create_window(unsigned long Line 3736  ui_seamless_create_window(unsigned long
3736                  ewmh_set_window_modal(wnd);                  ewmh_set_window_modal(wnd);
3737          }          }
3738    
3739            if (flags & SEAMLESSRDP_CREATE_TOPMOST)
3740            {
3741                    /* Make window always-on-top */
3742                    ewmh_set_window_above(wnd);
3743            }
3744    
3745          /* FIXME: Support for Input Context:s */          /* FIXME: Support for Input Context:s */
3746    
3747          get_input_mask(&input_mask);          get_input_mask(&input_mask);
# Line 3414  ui_seamless_create_window(unsigned long Line 3749  ui_seamless_create_window(unsigned long
3749    
3750          XSelectInput(g_display, wnd, input_mask);          XSelectInput(g_display, wnd, input_mask);
3751    
3752          /* 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 */  
3753          XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);          XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);
3754    
3755          sw = xmalloc(sizeof(seamless_window));          sw = xmalloc(sizeof(seamless_window));
3756    
3757            memset(sw, 0, sizeof(seamless_window));
3758    
3759          sw->wnd = wnd;          sw->wnd = wnd;
3760          sw->id = id;          sw->id = id;
         sw->behind = 0;  
3761          sw->group = sw_find_group(group, False);          sw->group = sw_find_group(group, False);
3762          sw->group->refcnt++;          sw->group->refcnt++;
         sw->xoffset = 0;  
         sw->yoffset = 0;  
         sw->width = 0;  
         sw->height = 0;  
3763          sw->state = SEAMLESSRDP_NOTYETMAPPED;          sw->state = SEAMLESSRDP_NOTYETMAPPED;
3764          sw->desktop = 0;          sw->desktop = 0;
3765          sw->position_timer = xmalloc(sizeof(struct timeval));          sw->position_timer = xmalloc(sizeof(struct timeval));
# Line 3496  ui_seamless_destroy_group(unsigned long Line 3827  ui_seamless_destroy_group(unsigned long
3827    
3828    
3829  void  void
3830    ui_seamless_seticon(unsigned long id, const char *format, int width, int height, int chunk,
3831                        const char *data, int chunk_len)
3832    {
3833            seamless_window *sw;
3834    
3835            if (!g_seamless_active)
3836                    return;
3837    
3838            sw = sw_get_window_by_id(id);
3839            if (!sw)
3840            {
3841                    warning("ui_seamless_seticon: No information for window 0x%lx\n", id);
3842                    return;
3843            }
3844    
3845            if (chunk == 0)
3846            {
3847                    if (sw->icon_size)
3848                            warning("ui_seamless_seticon: New icon started before previous completed\n");
3849    
3850                    if (strcmp(format, "RGBA") != 0)
3851                    {
3852                            warning("ui_seamless_seticon: Uknown icon format \"%s\"\n", format);
3853                            return;
3854                    }
3855    
3856                    sw->icon_size = width * height * 4;
3857                    if (sw->icon_size > 32 * 32 * 4)
3858                    {
3859                            warning("ui_seamless_seticon: Icon too large (%d bytes)\n", sw->icon_size);
3860                            sw->icon_size = 0;
3861                            return;
3862                    }
3863    
3864                    sw->icon_offset = 0;
3865            }
3866            else
3867            {
3868                    if (!sw->icon_size)
3869                            return;
3870            }
3871    
3872            if (chunk_len > (sw->icon_size - sw->icon_offset))
3873            {
3874                    warning("ui_seamless_seticon: Too large chunk received (%d bytes > %d bytes)\n",
3875                            chunk_len, sw->icon_size - sw->icon_offset);
3876                    sw->icon_size = 0;
3877                    return;
3878            }
3879    
3880            memcpy(sw->icon_buffer + sw->icon_offset, data, chunk_len);
3881            sw->icon_offset += chunk_len;
3882    
3883            if (sw->icon_offset == sw->icon_size)
3884            {
3885                    ewmh_set_icon(sw->wnd, width, height, sw->icon_buffer);
3886                    sw->icon_size = 0;
3887            }
3888    }
3889    
3890    
3891    void
3892    ui_seamless_delicon(unsigned long id, const char *format, int width, int height)
3893    {
3894            seamless_window *sw;
3895    
3896            if (!g_seamless_active)
3897                    return;
3898    
3899            sw = sw_get_window_by_id(id);
3900            if (!sw)
3901            {
3902                    warning("ui_seamless_seticon: No information for window 0x%lx\n", id);
3903                    return;
3904            }
3905    
3906            if (strcmp(format, "RGBA") != 0)
3907            {
3908                    warning("ui_seamless_seticon: Uknown icon format \"%s\"\n", format);
3909                    return;
3910            }
3911    
3912            ewmh_del_icon(sw->wnd, width, height);
3913    }
3914    
3915    
3916    void
3917  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)
3918  {  {
3919          seamless_window *sw;          seamless_window *sw;
# Line 3541  void Line 3959  void
3959  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)
3960  {  {
3961          seamless_window *sw;          seamless_window *sw;
3962            XWindowChanges values;
3963            unsigned long restack_serial;
3964    
3965          if (!g_seamless_active)          if (!g_seamless_active)
3966                  return;                  return;
# Line 3555  ui_seamless_restack_window(unsigned long Line 3975  ui_seamless_restack_window(unsigned long
3975          if (behind)          if (behind)
3976          {          {
3977                  seamless_window *sw_behind;                  seamless_window *sw_behind;
                 Window wnds[2];  
3978    
3979                  sw_behind = sw_get_window_by_id(behind);                  sw_behind = sw_get_window_by_id(behind);
3980                  if (!sw_behind)                  if (!sw_behind)
3981                  {                  {
3982                          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);  
3983                          return;                          return;
3984                  }                  }
3985    
3986                  wnds[1] = sw_behind->wnd;                  if (!g_seamless_broken_restack)
3987                  wnds[0] = sw->wnd;                  {
3988                            values.stack_mode = Below;
3989                  XRestackWindows(g_display, wnds, 2);                          values.sibling = sw_behind->wnd;
3990                            restack_serial = XNextRequest(g_display);
3991                            XReconfigureWMWindow(g_display, sw->wnd, DefaultScreen(g_display),
3992                                                 CWStackMode | CWSibling, &values);
3993                            sw_wait_configurenotify(sw->wnd, restack_serial);
3994                    }
3995          }          }
3996          else          else
3997          {          {
3998                  XRaiseWindow(g_display, sw->wnd);                  values.stack_mode = Above;
3999                    restack_serial = XNextRequest(g_display);
4000                    XReconfigureWMWindow(g_display, sw->wnd, DefaultScreen(g_display), CWStackMode,
4001                                         &values);
4002                    sw_wait_configurenotify(sw->wnd, restack_serial);
4003          }          }
4004    
4005          sw_restack_window(sw, behind);          sw_restack_window(sw, behind);
4006    
4007            if (flags & SEAMLESSRDP_CREATE_TOPMOST)
4008            {
4009                    /* Make window always-on-top */
4010                    ewmh_set_window_above(sw->wnd);
4011            }
4012  }  }
4013    
4014    

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

  ViewVC Help
Powered by ViewVC 1.1.26