56 |
unsigned long id; |
unsigned long id; |
57 |
int xoffset, yoffset; |
int xoffset, yoffset; |
58 |
int width, height; |
int width, height; |
59 |
|
unsigned int state; /* normal/minimized/maximized */ |
60 |
struct _seamless_window *next; |
struct _seamless_window *next; |
61 |
} seamless_window; |
} seamless_window; |
62 |
static seamless_window *g_seamless_windows = NULL; |
static seamless_window *g_seamless_windows = NULL; |
84 |
static Cursor g_current_cursor; |
static Cursor g_current_cursor; |
85 |
static HCURSOR g_null_cursor = NULL; |
static HCURSOR g_null_cursor = NULL; |
86 |
static Atom g_protocol_atom, g_kill_atom; |
static Atom g_protocol_atom, g_kill_atom; |
87 |
|
extern Atom g_net_wm_state_atom; |
88 |
static BOOL g_focused; |
static BOOL g_focused; |
89 |
static BOOL g_mouse_in_wnd; |
static BOOL g_mouse_in_wnd; |
90 |
/* Indicates that: |
/* Indicates that: |
1398 |
g_IM = XOpenIM(g_display, NULL, NULL, NULL); |
g_IM = XOpenIM(g_display, NULL, NULL, NULL); |
1399 |
|
|
1400 |
xclip_init(); |
xclip_init(); |
1401 |
|
ewmh_init(); |
1402 |
if (g_seamless_rdp) |
if (g_seamless_rdp) |
1403 |
seamless_init(); |
seamless_init(); |
1404 |
|
|
1734 |
char str[256]; |
char str[256]; |
1735 |
Status status; |
Status status; |
1736 |
int events = 0; |
int events = 0; |
1737 |
|
seamless_window *sw; |
1738 |
|
|
1739 |
while ((XPending(g_display) > 0) && events++ < 20) |
while ((XPending(g_display) > 0) && events++ < 20) |
1740 |
{ |
{ |
1897 |
} |
} |
1898 |
else |
else |
1899 |
{ |
{ |
|
seamless_window *sw; |
|
1900 |
sw = seamless_get_window_by_wnd(xevent.xexpose.window); |
sw = seamless_get_window_by_wnd(xevent.xexpose.window); |
1901 |
if (sw) |
if (sw) |
1902 |
XCopyArea(g_display, g_backstore, |
XCopyArea(g_display, g_backstore, |
1906 |
xevent.xexpose.width, |
xevent.xexpose.width, |
1907 |
xevent.xexpose.height, xevent.xexpose.x, |
xevent.xexpose.height, xevent.xexpose.x, |
1908 |
xevent.xexpose.y); |
xevent.xexpose.y); |
1909 |
|
else |
1910 |
|
{ |
1911 |
|
error("Expose for unknown window 0x%lx\n", |
1912 |
|
xevent.xexpose.window); |
1913 |
|
} |
1914 |
} |
} |
1915 |
|
|
1916 |
break; |
break; |
1941 |
break; |
break; |
1942 |
case PropertyNotify: |
case PropertyNotify: |
1943 |
xclip_handle_PropertyNotify(&xevent.xproperty); |
xclip_handle_PropertyNotify(&xevent.xproperty); |
1944 |
|
if (xevent.xproperty.window == g_wnd) |
1945 |
|
break; |
1946 |
|
if (xevent.xproperty.window == DefaultRootWindow(g_display)) |
1947 |
|
break; |
1948 |
|
|
1949 |
|
/* seamless */ |
1950 |
|
sw = seamless_get_window_by_wnd(xevent.xproperty.window); |
1951 |
|
if (!sw) |
1952 |
|
break; |
1953 |
|
|
1954 |
|
if ((xevent.xproperty.atom == g_net_wm_state_atom) |
1955 |
|
&& (xevent.xproperty.state == PropertyNewValue)) |
1956 |
|
{ |
1957 |
|
sw->state = ewmh_get_window_state(sw->wnd); |
1958 |
|
seamless_send_state(sw->id, sw->state, 0); |
1959 |
|
} |
1960 |
break; |
break; |
1961 |
case MapNotify: |
case MapNotify: |
1962 |
if (!g_seamless_rdp) |
if (!g_seamless_rdp) |
3011 |
} |
} |
3012 |
|
|
3013 |
void |
void |
3014 |
ui_seamless_create_window(unsigned long id, unsigned long flags) |
ui_seamless_create_window(unsigned long id, unsigned long parent, unsigned long flags) |
3015 |
{ |
{ |
3016 |
Window wnd; |
Window wnd; |
3017 |
XSetWindowAttributes attribs; |
XSetWindowAttributes attribs; |
3018 |
XClassHint *classhints; |
XClassHint *classhints; |
3019 |
long input_mask; |
long input_mask; |
3020 |
seamless_window *sw; |
seamless_window *sw, *sw_parent; |
3021 |
|
|
3022 |
get_window_attribs(&attribs); |
get_window_attribs(&attribs); |
3023 |
|
|
3043 |
XFree(classhints); |
XFree(classhints); |
3044 |
} |
} |
3045 |
|
|
3046 |
|
/* Set WM_TRANSIENT_FOR, if necessary */ |
3047 |
|
if (parent) |
3048 |
|
{ |
3049 |
|
sw_parent = seamless_get_window_by_id(parent); |
3050 |
|
if (sw_parent) |
3051 |
|
XSetTransientForHint(g_display, wnd, sw_parent->wnd); |
3052 |
|
else |
3053 |
|
warning("ui_seamless_create_window: No parent window 0x%lx\n", parent); |
3054 |
|
} |
3055 |
|
|
3056 |
/* FIXME: Support for Input Context:s */ |
/* FIXME: Support for Input Context:s */ |
3057 |
|
|
3058 |
get_input_mask(&input_mask); |
get_input_mask(&input_mask); |
3059 |
|
input_mask |= PropertyChangeMask; |
3060 |
|
|
3061 |
XSelectInput(g_display, wnd, input_mask); |
XSelectInput(g_display, wnd, input_mask); |
3062 |
|
|
3083 |
ui_seamless_destroy_window(unsigned long id, unsigned long flags) |
ui_seamless_destroy_window(unsigned long id, unsigned long flags) |
3084 |
{ |
{ |
3085 |
seamless_window *sw; |
seamless_window *sw; |
|
sw = seamless_get_window_by_id(id); |
|
3086 |
|
|
3087 |
|
sw = seamless_get_window_by_id(id); |
3088 |
if (!sw) |
if (!sw) |
3089 |
{ |
{ |
3090 |
warning("ui_seamless_destroy_window: No information for window 0x%lx\n", id); |
warning("ui_seamless_destroy_window: No information for window 0x%lx\n", id); |
3102 |
seamless_window *sw; |
seamless_window *sw; |
3103 |
|
|
3104 |
sw = seamless_get_window_by_id(id); |
sw = seamless_get_window_by_id(id); |
|
|
|
3105 |
if (!sw) |
if (!sw) |
3106 |
{ |
{ |
3107 |
warning("ui_seamless_move_window: No information for window 0x%lx\n", id); |
warning("ui_seamless_move_window: No information for window 0x%lx\n", id); |
3123 |
sw->width = MIN(MIN(width, width + x), g_width - sw->xoffset); |
sw->width = MIN(MIN(width, width + x), g_width - sw->xoffset); |
3124 |
sw->height = MIN(MIN(height, height + y), g_height - sw->yoffset); |
sw->height = MIN(MIN(height, height + y), g_height - sw->yoffset); |
3125 |
|
|
3126 |
|
/* If we move the window in a maximized state, then KDE won't |
3127 |
|
accept restoration */ |
3128 |
|
if (sw->state != SEAMLESSRDP_NORMAL) |
3129 |
|
return; |
3130 |
|
|
3131 |
/* FIXME: Perhaps use ewmh_net_moveresize_window instead */ |
/* FIXME: Perhaps use ewmh_net_moveresize_window instead */ |
3132 |
XMoveResizeWindow(g_display, sw->wnd, sw->xoffset, sw->yoffset, sw->width, sw->height); |
XMoveResizeWindow(g_display, sw->wnd, sw->xoffset, sw->yoffset, sw->width, sw->height); |
3133 |
} |
} |
3134 |
|
|
3135 |
|
|
3136 |
void |
void |
3137 |
ui_seamless_settitle(unsigned long id, const char *title) |
ui_seamless_settitle(unsigned long id, const char *title, unsigned long flags) |
3138 |
{ |
{ |
3139 |
seamless_window *sw; |
seamless_window *sw; |
3140 |
|
|
3141 |
sw = seamless_get_window_by_id(id); |
sw = seamless_get_window_by_id(id); |
3142 |
|
if (!sw) |
3143 |
|
{ |
3144 |
|
warning("ui_seamless_settitle: No information for window 0x%lx\n", id); |
3145 |
|
return; |
3146 |
|
} |
3147 |
|
|
3148 |
XStoreName(g_display, sw->wnd, title); |
XStoreName(g_display, sw->wnd, title); |
3149 |
} |
} |
3155 |
seamless_window *sw; |
seamless_window *sw; |
3156 |
|
|
3157 |
sw = seamless_get_window_by_id(id); |
sw = seamless_get_window_by_id(id); |
3158 |
|
if (!sw) |
3159 |
|
{ |
3160 |
|
warning("ui_seamless_setstate: No information for window 0x%lx\n", id); |
3161 |
|
return; |
3162 |
|
} |
3163 |
|
|
3164 |
|
sw->state = state; |
3165 |
|
|
3166 |
switch (state) |
switch (state) |
3167 |
{ |
{ |
3168 |
case SEAMLESSRDP_NORMAL: |
case SEAMLESSRDP_NORMAL: |
3169 |
case SEAMLESSRDP_MAXIMIZED: |
case SEAMLESSRDP_MAXIMIZED: |
3170 |
/* FIXME */ |
ewmh_change_state(sw->wnd, state); |
3171 |
break; |
break; |
3172 |
case SEAMLESSRDP_MINIMIZED: |
case SEAMLESSRDP_MINIMIZED: |
3173 |
|
/* EWMH says: "if an Application asks to toggle _NET_WM_STATE_HIDDEN |
3174 |
|
the Window Manager should probably just ignore the request, since |
3175 |
|
_NET_WM_STATE_HIDDEN is a function of some other aspect of the window |
3176 |
|
such as minimization, rather than an independent state." Besides, |
3177 |
|
XIconifyWindow is easier. */ |
3178 |
XIconifyWindow(g_display, sw->wnd, DefaultScreen(g_display)); |
XIconifyWindow(g_display, sw->wnd, DefaultScreen(g_display)); |
3179 |
break; |
break; |
3180 |
default: |
default: |