You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2028 lines
58 KiB
2028 lines
58 KiB
/**
|
|
* xrdp: A Remote Desktop Protocol server.
|
|
*
|
|
* Copyright (C) Jay Sorg 2004-2014
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
* simple window manager
|
|
*/
|
|
|
|
#include "xrdp.h"
|
|
#include "log.h"
|
|
|
|
/*****************************************************************************/
|
|
struct xrdp_wm *APP_CC
|
|
xrdp_wm_create(struct xrdp_process *owner,
|
|
struct xrdp_client_info *client_info)
|
|
{
|
|
struct xrdp_wm *self = (struct xrdp_wm *)NULL;
|
|
char event_name[256];
|
|
int pid = 0;
|
|
|
|
/* initialize (zero out) local variables: */
|
|
g_memset(event_name, 0, sizeof(char) * 256);
|
|
|
|
self = (struct xrdp_wm *)g_malloc(sizeof(struct xrdp_wm), 1);
|
|
self->client_info = client_info;
|
|
self->screen = xrdp_bitmap_create(client_info->width,
|
|
client_info->height,
|
|
client_info->bpp,
|
|
WND_TYPE_SCREEN, self);
|
|
self->screen->wm = self;
|
|
self->pro_layer = owner;
|
|
self->session = owner->session;
|
|
pid = g_getpid();
|
|
g_snprintf(event_name, 255, "xrdp_%8.8x_wm_login_mode_event_%8.8x",
|
|
pid, owner->session_id);
|
|
log_message(LOG_LEVEL_DEBUG,event_name);
|
|
self->login_mode_event = g_create_wait_obj(event_name);
|
|
self->painter = xrdp_painter_create(self, self->session);
|
|
self->cache = xrdp_cache_create(self, self->session, self->client_info);
|
|
self->log = list_create();
|
|
self->log->auto_free = 1;
|
|
self->mm = xrdp_mm_create(self);
|
|
self->default_font = xrdp_font_create(self);
|
|
/* this will use built in keymap or load from file */
|
|
get_keymaps(self->session->client_info->keylayout, &(self->keymap));
|
|
xrdp_wm_set_login_mode(self, 0);
|
|
self->target_surface = self->screen;
|
|
self->current_surface_index = 0xffff; /* screen */
|
|
|
|
/* to store configuration from xrdp.ini */
|
|
self->xrdp_config = g_malloc(sizeof(struct xrdp_config), 1);
|
|
|
|
return self;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
void APP_CC
|
|
xrdp_wm_delete(struct xrdp_wm *self)
|
|
{
|
|
if (self == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
xrdp_mm_delete(self->mm);
|
|
xrdp_cache_delete(self->cache);
|
|
xrdp_painter_delete(self->painter);
|
|
xrdp_bitmap_delete(self->screen);
|
|
/* free the log */
|
|
list_delete(self->log);
|
|
/* free default font */
|
|
xrdp_font_delete(self->default_font);
|
|
g_delete_wait_obj(self->login_mode_event);
|
|
|
|
if (self->xrdp_config)
|
|
g_free(self->xrdp_config);
|
|
|
|
/* free self */
|
|
g_free(self);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
int APP_CC
|
|
xrdp_wm_send_palette(struct xrdp_wm *self)
|
|
{
|
|
return libxrdp_send_palette(self->session, self->palette);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
int APP_CC
|
|
xrdp_wm_send_bell(struct xrdp_wm *self)
|
|
{
|
|
return libxrdp_send_bell(self->session);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
int APP_CC
|
|
xrdp_wm_send_bitmap(struct xrdp_wm *self, struct xrdp_bitmap *bitmap,
|
|
int x, int y, int cx, int cy)
|
|
{
|
|
return libxrdp_send_bitmap(self->session, bitmap->width, bitmap->height,
|
|
bitmap->bpp, bitmap->data, x, y, cx, cy);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
int APP_CC
|
|
xrdp_wm_set_focused(struct xrdp_wm *self, struct xrdp_bitmap *wnd)
|
|
{
|
|
struct xrdp_bitmap *focus_out_control;
|
|
struct xrdp_bitmap *focus_in_control;
|
|
|
|
if (self == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (self->focused_window == wnd)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
focus_out_control = 0;
|
|
focus_in_control = 0;
|
|
|
|
if (self->focused_window != 0)
|
|
{
|
|
xrdp_bitmap_set_focus(self->focused_window, 0);
|
|
focus_out_control = self->focused_window->focused_control;
|
|
}
|
|
|
|
self->focused_window = wnd;
|
|
|
|
if (self->focused_window != 0)
|
|
{
|
|
xrdp_bitmap_set_focus(self->focused_window, 1);
|
|
focus_in_control = self->focused_window->focused_control;
|
|
}
|
|
|
|
xrdp_bitmap_invalidate(focus_out_control, 0);
|
|
xrdp_bitmap_invalidate(focus_in_control, 0);
|
|
return 0;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
static int APP_CC
|
|
xrdp_wm_get_pixel(char *data, int x, int y, int width, int bpp)
|
|
{
|
|
int start;
|
|
int shift;
|
|
|
|
if (bpp == 1)
|
|
{
|
|
width = (width + 7) / 8;
|
|
start = (y * width) + x / 8;
|
|
shift = x % 8;
|
|
return (data[start] & (0x80 >> shift)) != 0;
|
|
}
|
|
else if (bpp == 4)
|
|
{
|
|
width = (width + 1) / 2;
|
|
start = y * width + x / 2;
|
|
shift = x % 2;
|
|
|
|
if (shift == 0)
|
|
{
|
|
return (data[start] & 0xf0) >> 4;
|
|
}
|
|
else
|
|
{
|
|
return data[start] & 0x0f;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
int APP_CC
|
|
xrdp_wm_pointer(struct xrdp_wm *self, char *data, char *mask, int x, int y,
|
|
int bpp)
|
|
{
|
|
int bytes;
|
|
struct xrdp_pointer_item pointer_item;
|
|
|
|
if (bpp == 0)
|
|
{
|
|
bpp = 24;
|
|
}
|
|
bytes = ((bpp + 7) / 8) * 32 * 32;
|
|
g_memset(&pointer_item, 0, sizeof(struct xrdp_pointer_item));
|
|
pointer_item.x = x;
|
|
pointer_item.y = y;
|
|
pointer_item.bpp = bpp;
|
|
g_memcpy(pointer_item.data, data, bytes);
|
|
g_memcpy(pointer_item.mask, mask, 32 * 32 / 8);
|
|
self->screen->pointer = xrdp_cache_add_pointer(self->cache, &pointer_item);
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* returns error */
|
|
int APP_CC
|
|
xrdp_wm_load_pointer(struct xrdp_wm *self, char *file_name, char *data,
|
|
char *mask, int *x, int *y)
|
|
{
|
|
int fd;
|
|
int bpp;
|
|
int w;
|
|
int h;
|
|
int i;
|
|
int j;
|
|
int pixel;
|
|
int palette[16];
|
|
struct stream *fs;
|
|
|
|
if (!g_file_exist(file_name))
|
|
{
|
|
log_message(LOG_LEVEL_ERROR,"xrdp_wm_load_pointer: error pointer file [%s] does not exist",
|
|
file_name);
|
|
return 1;
|
|
}
|
|
|
|
make_stream(fs);
|
|
init_stream(fs, 8192);
|
|
fd = g_file_open(file_name);
|
|
|
|
if (fd < 0)
|
|
{
|
|
log_message(LOG_LEVEL_ERROR,"xrdp_wm_load_pointer: error loading pointer from file [%s]",
|
|
file_name);
|
|
xstream_free(fs);
|
|
return 1;
|
|
}
|
|
|
|
g_file_read(fd, fs->data, 8192);
|
|
g_file_close(fd);
|
|
in_uint8s(fs, 6);
|
|
in_uint8(fs, w);
|
|
in_uint8(fs, h);
|
|
in_uint8s(fs, 2);
|
|
in_uint16_le(fs, *x);
|
|
in_uint16_le(fs, *y);
|
|
in_uint8s(fs, 22);
|
|
in_uint8(fs, bpp);
|
|
in_uint8s(fs, 25);
|
|
|
|
if (w == 32 && h == 32)
|
|
{
|
|
if (bpp == 1)
|
|
{
|
|
for (i = 0; i < 2; i++)
|
|
{
|
|
in_uint32_le(fs, pixel);
|
|
palette[i] = pixel;
|
|
}
|
|
for (i = 0; i < 32; i++)
|
|
{
|
|
for (j = 0; j < 32; j++)
|
|
{
|
|
pixel = palette[xrdp_wm_get_pixel(fs->p, j, i, 32, 1)];
|
|
*data = pixel;
|
|
data++;
|
|
*data = pixel >> 8;
|
|
data++;
|
|
*data = pixel >> 16;
|
|
data++;
|
|
}
|
|
}
|
|
|
|
in_uint8s(fs, 128);
|
|
}
|
|
else if (bpp == 4)
|
|
{
|
|
for (i = 0; i < 16; i++)
|
|
{
|
|
in_uint32_le(fs, pixel);
|
|
palette[i] = pixel;
|
|
}
|
|
for (i = 0; i < 32; i++)
|
|
{
|
|
for (j = 0; j < 32; j++)
|
|
{
|
|
pixel = palette[xrdp_wm_get_pixel(fs->p, j, i, 32, 1)];
|
|
*data = pixel;
|
|
data++;
|
|
*data = pixel >> 8;
|
|
data++;
|
|
*data = pixel >> 16;
|
|
data++;
|
|
}
|
|
}
|
|
|
|
in_uint8s(fs, 512);
|
|
}
|
|
|
|
g_memcpy(mask, fs->p, 128); /* mask */
|
|
}
|
|
|
|
free_stream(fs);
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
int APP_CC
|
|
xrdp_wm_send_pointer(struct xrdp_wm *self, int cache_idx,
|
|
char *data, char *mask, int x, int y, int bpp)
|
|
{
|
|
return libxrdp_send_pointer(self->session, cache_idx, data, mask,
|
|
x, y, bpp);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
int APP_CC
|
|
xrdp_wm_set_pointer(struct xrdp_wm *self, int cache_idx)
|
|
{
|
|
return libxrdp_set_pointer(self->session, cache_idx);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* convert hex string to int */
|
|
unsigned int APP_CC
|
|
xrdp_wm_htoi (const char *ptr)
|
|
{
|
|
unsigned int value = 0;
|
|
char ch = *ptr;
|
|
|
|
while (ch == ' ' || ch == '\t')
|
|
{
|
|
ch = *(++ptr);
|
|
}
|
|
|
|
for (;;)
|
|
{
|
|
if (ch >= '0' && ch <= '9')
|
|
{
|
|
value = (value << 4) + (ch - '0');
|
|
}
|
|
else if (ch >= 'A' && ch <= 'F')
|
|
{
|
|
value = (value << 4) + (ch - 'A' + 10);
|
|
}
|
|
else if (ch >= 'a' && ch <= 'f')
|
|
{
|
|
value = (value << 4) + (ch - 'a' + 10);
|
|
}
|
|
else
|
|
{
|
|
return value;
|
|
}
|
|
|
|
ch = *(++ptr);
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
int APP_CC
|
|
xrdp_wm_load_static_colors_plus(struct xrdp_wm *self, char *autorun_name)
|
|
{
|
|
int bindex;
|
|
int gindex;
|
|
int rindex;
|
|
|
|
int fd;
|
|
int index;
|
|
char *val;
|
|
struct list *names;
|
|
struct list *values;
|
|
char cfg_file[256];
|
|
|
|
if (autorun_name != 0)
|
|
{
|
|
autorun_name[0] = 0;
|
|
}
|
|
|
|
/* initialize with defaults */
|
|
self->black = HCOLOR(self->screen->bpp, 0x000000);
|
|
self->grey = HCOLOR(self->screen->bpp, 0xc0c0c0);
|
|
self->dark_grey = HCOLOR(self->screen->bpp, 0x808080);
|
|
self->blue = HCOLOR(self->screen->bpp, 0x0000ff);
|
|
self->dark_blue = HCOLOR(self->screen->bpp, 0x00007f);
|
|
self->white = HCOLOR(self->screen->bpp, 0xffffff);
|
|
self->red = HCOLOR(self->screen->bpp, 0xff0000);
|
|
self->green = HCOLOR(self->screen->bpp, 0x00ff00);
|
|
self->background = HCOLOR(self->screen->bpp, 0x000000);
|
|
|
|
/* now load them from the globals in xrdp.ini if defined */
|
|
g_snprintf(cfg_file, 255, "%s/xrdp.ini", XRDP_CFG_PATH);
|
|
fd = g_file_open(cfg_file);
|
|
|
|
if (fd > 0)
|
|
{
|
|
names = list_create();
|
|
names->auto_free = 1;
|
|
values = list_create();
|
|
values->auto_free = 1;
|
|
|
|
if (file_read_section(fd, "globals", names, values) == 0)
|
|
{
|
|
for (index = 0; index < names->count; index++)
|
|
{
|
|
val = (char *)list_get_item(names, index);
|
|
|
|
if (val != 0)
|
|
{
|
|
if (g_strcasecmp(val, "black") == 0)
|
|
{
|
|
val = (char *)list_get_item(values, index);
|
|
self->black = HCOLOR(self->screen->bpp,xrdp_wm_htoi(val));
|
|
}
|
|
else if (g_strcasecmp(val, "grey") == 0)
|
|
{
|
|
val = (char *)list_get_item(values, index);
|
|
self->grey = HCOLOR(self->screen->bpp, xrdp_wm_htoi(val));
|
|
}
|
|
else if (g_strcasecmp(val, "dark_grey") == 0)
|
|
{
|
|
val = (char *)list_get_item(values, index);
|
|
self->dark_grey = HCOLOR(self->screen->bpp, xrdp_wm_htoi(val));
|
|
}
|
|
else if (g_strcasecmp(val, "blue") == 0)
|
|
{
|
|
val = (char *)list_get_item(values, index);
|
|
self->blue = HCOLOR(self->screen->bpp, xrdp_wm_htoi(val));
|
|
}
|
|
else if (g_strcasecmp(val, "dark_blue") == 0)
|
|
{
|
|
val = (char *)list_get_item(values, index);
|
|
self->dark_blue = HCOLOR(self->screen->bpp, xrdp_wm_htoi(val));
|
|
}
|
|
else if (g_strcasecmp(val, "white") == 0)
|
|
{
|
|
val = (char *)list_get_item(values, index);
|
|
self->white = HCOLOR(self->screen->bpp, xrdp_wm_htoi(val));
|
|
}
|
|
else if (g_strcasecmp(val, "red") == 0)
|
|
{
|
|
val = (char *)list_get_item(values, index);
|
|
self->red = HCOLOR(self->screen->bpp, xrdp_wm_htoi(val));
|
|
}
|
|
else if (g_strcasecmp(val, "green") == 0)
|
|
{
|
|
val = (char *)list_get_item(values, index);
|
|
self->green = HCOLOR(self->screen->bpp, xrdp_wm_htoi(val));
|
|
}
|
|
else if (g_strcasecmp(val, "background") == 0)
|
|
{
|
|
val = (char *)list_get_item(values, index);
|
|
self->background = HCOLOR(self->screen->bpp, xrdp_wm_htoi(val));
|
|
}
|
|
else if (g_strcasecmp(val, "autorun") == 0)
|
|
{
|
|
val = (char *)list_get_item(values, index);
|
|
|
|
if (autorun_name != 0)
|
|
{
|
|
g_strncpy(autorun_name, val, 255);
|
|
}
|
|
}
|
|
else if (g_strcasecmp(val, "hidelogwindow") == 0)
|
|
{
|
|
val = (char *)list_get_item(values, index);
|
|
self->hide_log_window = g_text2bool(val);
|
|
}
|
|
else if (g_strcasecmp(val, "pamerrortxt") == 0)
|
|
{
|
|
val = (char *)list_get_item(values, index);
|
|
g_strncpy(self->pamerrortxt, val, 255);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
list_delete(names);
|
|
list_delete(values);
|
|
g_file_close(fd);
|
|
}
|
|
else
|
|
{
|
|
log_message(LOG_LEVEL_ERROR,"xrdp_wm_load_static_colors: Could not read xrdp.ini file %s", cfg_file);
|
|
}
|
|
|
|
if (self->screen->bpp == 8)
|
|
{
|
|
/* rgb332 */
|
|
for (bindex = 0; bindex < 4; bindex++)
|
|
{
|
|
for (gindex = 0; gindex < 8; gindex++)
|
|
{
|
|
for (rindex = 0; rindex < 8; rindex++)
|
|
{
|
|
self->palette[(bindex << 6) | (gindex << 3) | rindex] =
|
|
(((rindex << 5) | (rindex << 2) | (rindex >> 1)) << 16) |
|
|
(((gindex << 5) | (gindex << 2) | (gindex >> 1)) << 8) |
|
|
((bindex << 6) | (bindex << 4) | (bindex << 2) | (bindex));
|
|
}
|
|
}
|
|
}
|
|
|
|
xrdp_wm_send_palette(self);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* returns error */
|
|
int APP_CC
|
|
xrdp_wm_load_static_pointers(struct xrdp_wm *self)
|
|
{
|
|
struct xrdp_pointer_item pointer_item;
|
|
char file_path[256];
|
|
|
|
DEBUG(("sending cursor"));
|
|
g_snprintf(file_path, 255, "%s/cursor1.cur", XRDP_SHARE_PATH);
|
|
g_memset(&pointer_item, 0, sizeof(pointer_item));
|
|
xrdp_wm_load_pointer(self, file_path, pointer_item.data,
|
|
pointer_item.mask, &pointer_item.x, &pointer_item.y);
|
|
xrdp_cache_add_pointer_static(self->cache, &pointer_item, 1);
|
|
DEBUG(("sending cursor"));
|
|
g_snprintf(file_path, 255, "%s/cursor0.cur", XRDP_SHARE_PATH);
|
|
g_memset(&pointer_item, 0, sizeof(pointer_item));
|
|
xrdp_wm_load_pointer(self, file_path, pointer_item.data,
|
|
pointer_item.mask, &pointer_item.x, &pointer_item.y);
|
|
xrdp_cache_add_pointer_static(self->cache, &pointer_item, 0);
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
int APP_CC
|
|
xrdp_wm_init(struct xrdp_wm *self)
|
|
{
|
|
int fd;
|
|
int index;
|
|
struct list *names;
|
|
struct list *values;
|
|
char *q;
|
|
char *r;
|
|
char param[256];
|
|
char section_name[256];
|
|
char cfg_file[256];
|
|
char autorun_name[256];
|
|
|
|
g_writeln("in xrdp_wm_init: ");
|
|
|
|
load_xrdp_config(self->xrdp_config, self->screen->bpp);
|
|
|
|
xrdp_wm_load_static_colors_plus(self, autorun_name);
|
|
xrdp_wm_load_static_pointers(self);
|
|
self->screen->bg_color = self->xrdp_config->cfg_globals.ls_top_window_bg_color;
|
|
|
|
if (self->session->client_info->rdp_autologin || self->hide_log_window)
|
|
{
|
|
/*
|
|
* NOTE: this should eventually be accessed from self->xrdp_config
|
|
*/
|
|
|
|
g_snprintf(cfg_file, 255, "%s/xrdp.ini", XRDP_CFG_PATH);
|
|
fd = g_file_open(cfg_file); /* xrdp.ini */
|
|
if (fd != -1)
|
|
{
|
|
names = list_create();
|
|
names->auto_free = 1;
|
|
values = list_create();
|
|
values->auto_free = 1;
|
|
|
|
/* look for module name to be loaded */
|
|
if (autorun_name[0] != 0)
|
|
{
|
|
/* if autorun is configured in xrdp.ini, we enforce that module to be loaded */
|
|
g_strncpy(section_name, autorun_name, 255);
|
|
}
|
|
else if (self->session->client_info->domain[0] != '_')
|
|
{
|
|
/* domain names that starts with '_' are reserved for IP/DNS to
|
|
* simplify for the user in a proxy setup */
|
|
|
|
/* we use the domain name as the module name to be loaded */
|
|
g_strncpy(section_name, self->session->client_info->domain,
|
|
255);
|
|
}
|
|
else
|
|
{
|
|
/* if no domain is passed, and no autorun in xrdp.ini,
|
|
use the first item in the xrdp.ini
|
|
file that's not named
|
|
'globals' or 'Logging' or 'channels' */
|
|
/* TODO: change this and have an 'autologin'
|
|
line in globals section */
|
|
file_read_sections(fd, names);
|
|
for (index = 0; index < names->count; index++)
|
|
{
|
|
q = (char *)list_get_item(names, index);
|
|
if ((g_strncasecmp("globals", q, 8) != 0) &&
|
|
(g_strncasecmp("Logging", q, 8) != 0) &&
|
|
(g_strncasecmp("channels", q, 9) != 0))
|
|
{
|
|
g_strncpy(section_name, q, 255);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
list_clear(names);
|
|
|
|
/* look for the required module in xrdp.ini, fetch its parameters */
|
|
if (file_read_section(fd, section_name, names, values) == 0)
|
|
{
|
|
for (index = 0; index < names->count; index++)
|
|
{
|
|
q = (char *)list_get_item(names, index);
|
|
r = (char *)list_get_item(values, index);
|
|
|
|
if (g_strncmp("password", q, 255) == 0)
|
|
{
|
|
/* if the password has been asked for by the module, use what the
|
|
client says.
|
|
if the password has been manually set in the config, use that
|
|
instead of what the client says. */
|
|
if (g_strncmp("ask", r, 3) == 0)
|
|
{
|
|
r = self->session->client_info->password;
|
|
}
|
|
}
|
|
else if (g_strncmp("username", q, 255) == 0)
|
|
{
|
|
/* if the username has been asked for by the module, use what the
|
|
client says.
|
|
if the username has been manually set in the config, use that
|
|
instead of what the client says. */
|
|
if (g_strncmp("ask", r, 3) == 0)
|
|
{
|
|
r = self->session->client_info->username;
|
|
}
|
|
}
|
|
else if (g_strncmp("ip", q, 255) == 0)
|
|
{
|
|
/* if the ip has been asked for by the module, use what the
|
|
client says (target ip should be in 'domain' field, when starting with "_")
|
|
if the ip has been manually set in the config, use that
|
|
instead of what the client says. */
|
|
if (g_strncmp("ask", r, 3) == 0)
|
|
{
|
|
if (self->session->client_info->domain[0] == '_')
|
|
{
|
|
g_strncpy(param, &self->session->client_info->domain[1], 255);
|
|
r = param;
|
|
}
|
|
|
|
}
|
|
}
|
|
else if (g_strncmp("port", q, 255) == 0)
|
|
{
|
|
if (g_strncmp("ask3389", r, 7) == 0)
|
|
{
|
|
r = "3389"; /* use default */
|
|
}
|
|
}
|
|
|
|
list_add_item(self->mm->login_names, (long)g_strdup(q));
|
|
list_add_item(self->mm->login_values, (long)g_strdup(r));
|
|
}
|
|
|
|
xrdp_wm_set_login_mode(self, 2);
|
|
}
|
|
else
|
|
{
|
|
/* requested module name not found in xrdp.ini */
|
|
g_writeln(" xrdp_wm_init: file_read_section returned non-zero, requested section not found in xrdp.ini");
|
|
xrdp_wm_log_msg(self, "ERROR: The requested xrdp module not found in xrdp.ini,"
|
|
" falling back to login window");
|
|
}
|
|
|
|
list_delete(names);
|
|
list_delete(values);
|
|
g_file_close(fd);
|
|
}
|
|
else
|
|
{
|
|
log_message(LOG_LEVEL_ERROR,"xrdp_wm_init: Could not read xrdp.ini file %s", cfg_file);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
g_writeln(" xrdp_wm_init: no autologin / auto run detected, draw login window");
|
|
xrdp_login_wnd_create(self);
|
|
/* clear screen */
|
|
xrdp_bitmap_invalidate(self->screen, 0);
|
|
xrdp_wm_set_focused(self, self->login_window);
|
|
xrdp_wm_set_login_mode(self, 1);
|
|
}
|
|
|
|
g_writeln("out xrdp_wm_init: ");
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* returns the number for rects visible for an area relative to a drawable */
|
|
/* putting the rects in region */
|
|
int APP_CC
|
|
xrdp_wm_get_vis_region(struct xrdp_wm *self, struct xrdp_bitmap *bitmap,
|
|
int x, int y, int cx, int cy,
|
|
struct xrdp_region *region, int clip_children)
|
|
{
|
|
int i;
|
|
struct xrdp_bitmap *p;
|
|
struct xrdp_rect a;
|
|
struct xrdp_rect b;
|
|
|
|
/* area we are drawing */
|
|
MAKERECT(a, bitmap->left + x, bitmap->top + y, cx, cy);
|
|
p = bitmap->parent;
|
|
|
|
while (p != 0)
|
|
{
|
|
RECTOFFSET(a, p->left, p->top);
|
|
p = p->parent;
|
|
}
|
|
|
|
a.left = MAX(self->screen->left, a.left);
|
|
a.top = MAX(self->screen->top, a.top);
|
|
a.right = MIN(self->screen->left + self->screen->width, a.right);
|
|
a.bottom = MIN(self->screen->top + self->screen->height, a.bottom);
|
|
xrdp_region_add_rect(region, &a);
|
|
|
|
if (clip_children)
|
|
{
|
|
/* loop through all windows in z order */
|
|
for (i = 0; i < self->screen->child_list->count; i++)
|
|
{
|
|
p = (struct xrdp_bitmap *)list_get_item(self->screen->child_list, i);
|
|
|
|
if (p == bitmap || p == bitmap->parent)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
MAKERECT(b, p->left, p->top, p->width, p->height);
|
|
xrdp_region_subtract_rect(region, &b);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* return the window at x, y on the screen */
|
|
static struct xrdp_bitmap *APP_CC
|
|
xrdp_wm_at_pos(struct xrdp_bitmap *wnd, int x, int y,
|
|
struct xrdp_bitmap **wnd1)
|
|
{
|
|
int i;
|
|
struct xrdp_bitmap *p;
|
|
struct xrdp_bitmap *q;
|
|
|
|
/* loop through all windows in z order */
|
|
for (i = 0; i < wnd->child_list->count; i++)
|
|
{
|
|
p = (struct xrdp_bitmap *)list_get_item(wnd->child_list, i);
|
|
|
|
if (x >= p->left && y >= p->top && x < p->left + p->width &&
|
|
y < p->top + p->height)
|
|
{
|
|
if (wnd1 != 0)
|
|
{
|
|
*wnd1 = p;
|
|
}
|
|
|
|
q = xrdp_wm_at_pos(p, x - p->left, y - p->top, 0);
|
|
|
|
if (q == 0)
|
|
{
|
|
return p;
|
|
}
|
|
else
|
|
{
|
|
return q;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
static int APP_CC
|
|
xrdp_wm_xor_pat(struct xrdp_wm *self, int x, int y, int cx, int cy)
|
|
{
|
|
self->painter->clip_children = 0;
|
|
self->painter->rop = 0x5a;
|
|
xrdp_painter_begin_update(self->painter);
|
|
self->painter->use_clip = 0;
|
|
self->painter->mix_mode = 1;
|
|
self->painter->brush.pattern[0] = 0xaa;
|
|
self->painter->brush.pattern[1] = 0x55;
|
|
self->painter->brush.pattern[2] = 0xaa;
|
|
self->painter->brush.pattern[3] = 0x55;
|
|
self->painter->brush.pattern[4] = 0xaa;
|
|
self->painter->brush.pattern[5] = 0x55;
|
|
self->painter->brush.pattern[6] = 0xaa;
|
|
self->painter->brush.pattern[7] = 0x55;
|
|
self->painter->brush.x_origin = 0;
|
|
self->painter->brush.x_origin = 0;
|
|
self->painter->brush.style = 3;
|
|
self->painter->bg_color = self->black;
|
|
self->painter->fg_color = self->white;
|
|
/* top */
|
|
xrdp_painter_fill_rect(self->painter, self->screen, x, y, cx, 5);
|
|
/* bottom */
|
|
xrdp_painter_fill_rect(self->painter, self->screen, x, y + (cy - 5), cx, 5);
|
|
/* left */
|
|
xrdp_painter_fill_rect(self->painter, self->screen, x, y + 5, 5, cy - 10);
|
|
/* right */
|
|
xrdp_painter_fill_rect(self->painter, self->screen, x + (cx - 5), y + 5, 5,
|
|
cy - 10);
|
|
xrdp_painter_end_update(self->painter);
|
|
self->painter->rop = 0xcc;
|
|
self->painter->clip_children = 1;
|
|
self->painter->mix_mode = 0;
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* this don't are about nothing, just copy the bits */
|
|
/* no clipping rects, no windows in the way, nothing */
|
|
static int APP_CC
|
|
xrdp_wm_bitblt(struct xrdp_wm *self,
|
|
struct xrdp_bitmap *dst, int dx, int dy,
|
|
struct xrdp_bitmap *src, int sx, int sy,
|
|
int sw, int sh, int rop)
|
|
{
|
|
// int i;
|
|
// int line_size;
|
|
// int Bpp;
|
|
// char* s;
|
|
// char* d;
|
|
|
|
// if (sw <= 0 || sh <= 0)
|
|
// return 0;
|
|
if (self->screen == dst && self->screen == src)
|
|
{
|
|
/* send a screen blt */
|
|
// Bpp = (dst->bpp + 7) / 8;
|
|
// line_size = sw * Bpp;
|
|
// s = src->data + (sy * src->width + sx) * Bpp;
|
|
// d = dst->data + (dy * dst->width + dx) * Bpp;
|
|
// for (i = 0; i < sh; i++)
|
|
// {
|
|
// //g_memcpy(d, s, line_size);
|
|
// s += src->width * Bpp;
|
|
// d += dst->width * Bpp;
|
|
// }
|
|
libxrdp_orders_init(self->session);
|
|
libxrdp_orders_screen_blt(self->session, dx, dy, sw, sh, sx, sy, rop, 0);
|
|
libxrdp_orders_send(self->session);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* return true if rect is totally exposed going in reverse z order */
|
|
/* from wnd up */
|
|
static int APP_CC
|
|
xrdp_wm_is_rect_vis(struct xrdp_wm *self, struct xrdp_bitmap *wnd,
|
|
struct xrdp_rect *rect)
|
|
{
|
|
struct xrdp_rect wnd_rect;
|
|
struct xrdp_bitmap *b;
|
|
int i;;
|
|
|
|
/* if rect is part off screen */
|
|
if (rect->left < 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (rect->top < 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (rect->right >= self->screen->width)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (rect->bottom >= self->screen->height)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
i = list_index_of(self->screen->child_list, (long)wnd);
|
|
i--;
|
|
|
|
while (i >= 0)
|
|
{
|
|
b = (struct xrdp_bitmap *)list_get_item(self->screen->child_list, i);
|
|
MAKERECT(wnd_rect, b->left, b->top, b->width, b->height);
|
|
|
|
if (rect_intersect(rect, &wnd_rect, 0))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
i--;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
static int APP_CC
|
|
xrdp_wm_move_window(struct xrdp_wm *self, struct xrdp_bitmap *wnd,
|
|
int dx, int dy)
|
|
{
|
|
struct xrdp_rect rect1;
|
|
struct xrdp_rect rect2;
|
|
struct xrdp_region *r;
|
|
int i;
|
|
|
|
MAKERECT(rect1, wnd->left, wnd->top, wnd->width, wnd->height);
|
|
|
|
if (xrdp_wm_is_rect_vis(self, wnd, &rect1))
|
|
{
|
|
rect2 = rect1;
|
|
RECTOFFSET(rect2, dx, dy);
|
|
|
|
if (xrdp_wm_is_rect_vis(self, wnd, &rect2))
|
|
{
|
|
/* if both src and dst are unobscured, we can do a bitblt move */
|
|
xrdp_wm_bitblt(self, self->screen, wnd->left + dx, wnd->top + dy,
|
|
self->screen, wnd->left, wnd->top,
|
|
wnd->width, wnd->height, 0xcc);
|
|
wnd->left += dx;
|
|
wnd->top += dy;
|
|
r = xrdp_region_create(self);
|
|
xrdp_region_add_rect(r, &rect1);
|
|
xrdp_region_subtract_rect(r, &rect2);
|
|
i = 0;
|
|
|
|
while (xrdp_region_get_rect(r, i, &rect1) == 0)
|
|
{
|
|
xrdp_bitmap_invalidate(self->screen, &rect1);
|
|
i++;
|
|
}
|
|
|
|
xrdp_region_delete(r);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
wnd->left += dx;
|
|
wnd->top += dy;
|
|
xrdp_bitmap_invalidate(self->screen, &rect1);
|
|
xrdp_bitmap_invalidate(wnd, 0);
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
static int APP_CC
|
|
xrdp_wm_undraw_dragging_box(struct xrdp_wm *self, int do_begin_end)
|
|
{
|
|
int boxx;
|
|
int boxy;
|
|
|
|
if (self == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (self->dragging)
|
|
{
|
|
if (self->draggingxorstate)
|
|
{
|
|
if (do_begin_end)
|
|
{
|
|
xrdp_painter_begin_update(self->painter);
|
|
}
|
|
|
|
boxx = self->draggingx - self->draggingdx;
|
|
boxy = self->draggingy - self->draggingdy;
|
|
xrdp_wm_xor_pat(self, boxx, boxy, self->draggingcx, self->draggingcy);
|
|
self->draggingxorstate = 0;
|
|
|
|
if (do_begin_end)
|
|
{
|
|
xrdp_painter_end_update(self->painter);
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
static int APP_CC
|
|
xrdp_wm_draw_dragging_box(struct xrdp_wm *self, int do_begin_end)
|
|
{
|
|
int boxx;
|
|
int boxy;
|
|
|
|
if (self == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (self->dragging)
|
|
{
|
|
if (!self->draggingxorstate)
|
|
{
|
|
if (do_begin_end)
|
|
{
|
|
xrdp_painter_begin_update(self->painter);
|
|
}
|
|
|
|
boxx = self->draggingx - self->draggingdx;
|
|
boxy = self->draggingy - self->draggingdy;
|
|
xrdp_wm_xor_pat(self, boxx, boxy, self->draggingcx, self->draggingcy);
|
|
self->draggingxorstate = 1;
|
|
|
|
if (do_begin_end)
|
|
{
|
|
xrdp_painter_end_update(self->painter);
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
int APP_CC
|
|
xrdp_wm_mouse_move(struct xrdp_wm *self, int x, int y)
|
|
{
|
|
struct xrdp_bitmap *b;
|
|
|
|
if (self == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (x < 0)
|
|
{
|
|
x = 0;
|
|
}
|
|
|
|
if (y < 0)
|
|
{
|
|
y = 0;
|
|
}
|
|
|
|
if (x >= self->screen->width)
|
|
{
|
|
x = self->screen->width;
|
|
}
|
|
|
|
if (y >= self->screen->height)
|
|
{
|
|
y = self->screen->height;
|
|
}
|
|
|
|
self->mouse_x = x;
|
|
self->mouse_y = y;
|
|
|
|
if (self->dragging)
|
|
{
|
|
xrdp_painter_begin_update(self->painter);
|
|
xrdp_wm_undraw_dragging_box(self, 0);
|
|
self->draggingx = x;
|
|
self->draggingy = y;
|
|
xrdp_wm_draw_dragging_box(self, 0);
|
|
xrdp_painter_end_update(self->painter);
|
|
return 0;
|
|
}
|
|
|
|
b = xrdp_wm_at_pos(self->screen, x, y, 0);
|
|
|
|
if (b == 0) /* if b is null, the movement must be over the screen */
|
|
{
|
|
if (self->screen->pointer != self->current_pointer)
|
|
{
|
|
xrdp_wm_set_pointer(self, self->screen->pointer);
|
|
self->current_pointer = self->screen->pointer;
|
|
}
|
|
|
|
if (self->mm->mod != 0) /* if screen is mod controlled */
|
|
{
|
|
if (self->mm->mod->mod_event != 0)
|
|
{
|
|
self->mm->mod->mod_event(self->mm->mod, WM_MOUSEMOVE, x, y, 0, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (self->button_down != 0)
|
|
{
|
|
if (b == self->button_down && self->button_down->state == 0)
|
|
{
|
|
self->button_down->state = 1;
|
|
xrdp_bitmap_invalidate(self->button_down, 0);
|
|
}
|
|
else if (b != self->button_down)
|
|
{
|
|
self->button_down->state = 0;
|
|
xrdp_bitmap_invalidate(self->button_down, 0);
|
|
}
|
|
}
|
|
|
|
if (b != 0)
|
|
{
|
|
if (!self->dragging)
|
|
{
|
|
if (b->pointer != self->current_pointer)
|
|
{
|
|
xrdp_wm_set_pointer(self, b->pointer);
|
|
self->current_pointer = b->pointer;
|
|
}
|
|
|
|
xrdp_bitmap_def_proc(b, WM_MOUSEMOVE,
|
|
xrdp_bitmap_from_screenx(b, x),
|
|
xrdp_bitmap_from_screeny(b, y));
|
|
|
|
if (self->button_down == 0)
|
|
{
|
|
if (b->notify != 0)
|
|
{
|
|
b->notify(b->owner, b, 2, x, y);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
static int APP_CC
|
|
xrdp_wm_clear_popup(struct xrdp_wm *self)
|
|
{
|
|
int i;
|
|
struct xrdp_rect rect;
|
|
//struct xrdp_bitmap* b;
|
|
|
|
//b = 0;
|
|
if (self->popup_wnd != 0)
|
|
{
|
|
//b = self->popup_wnd->popped_from;
|
|
i = list_index_of(self->screen->child_list, (long)self->popup_wnd);
|
|
list_remove_item(self->screen->child_list, i);
|
|
MAKERECT(rect, self->popup_wnd->left, self->popup_wnd->top,
|
|
self->popup_wnd->width, self->popup_wnd->height);
|
|
xrdp_bitmap_invalidate(self->screen, &rect);
|
|
xrdp_bitmap_delete(self->popup_wnd);
|
|
}
|
|
|
|
//xrdp_wm_set_focused(self, b->parent);
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
int APP_CC
|
|
xrdp_wm_mouse_click(struct xrdp_wm *self, int x, int y, int but, int down)
|
|
{
|
|
struct xrdp_bitmap *control;
|
|
struct xrdp_bitmap *focus_out_control;
|
|
struct xrdp_bitmap *wnd;
|
|
int newx;
|
|
int newy;
|
|
int oldx;
|
|
int oldy;
|
|
|
|
if (self == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (x < 0)
|
|
{
|
|
x = 0;
|
|
}
|
|
|
|
if (y < 0)
|
|
{
|
|
y = 0;
|
|
}
|
|
|
|
if (x >= self->screen->width)
|
|
{
|
|
x = self->screen->width;
|
|
}
|
|
|
|
if (y >= self->screen->height)
|
|
{
|
|
y = self->screen->height;
|
|
}
|
|
|
|
if (self->dragging && but == 1 && !down && self->dragging_window != 0)
|
|
{
|
|
/* if done dragging */
|
|
self->draggingx = x;
|
|
self->draggingy = y;
|
|
newx = self->draggingx - self->draggingdx;
|
|
newy = self->draggingy - self->draggingdy;
|
|
oldx = self->dragging_window->left;
|
|
oldy = self->dragging_window->top;
|
|
|
|
/* draw xor box one more time */
|
|
if (self->draggingxorstate)
|
|
{
|
|
xrdp_wm_xor_pat(self, newx, newy, self->draggingcx, self->draggingcy);
|
|
}
|
|
|
|
self->draggingxorstate = 0;
|
|
/* move screen to new location */
|
|
xrdp_wm_move_window(self, self->dragging_window, newx - oldx, newy - oldy);
|
|
self->dragging_window = 0;
|
|
self->dragging = 0;
|
|
}
|
|
|
|
wnd = 0;
|
|
control = xrdp_wm_at_pos(self->screen, x, y, &wnd);
|
|
|
|
if (control == 0)
|
|
{
|
|
if (self->mm->mod != 0) /* if screen is mod controlled */
|
|
{
|
|
if (self->mm->mod->mod_event != 0)
|
|
{
|
|
if (but == 1 && down)
|
|
{
|
|
self->mm->mod->mod_event(self->mm->mod, WM_LBUTTONDOWN, x, y, 0, 0);
|
|
}
|
|
else if (but == 1 && !down)
|
|
{
|
|
self->mm->mod->mod_event(self->mm->mod, WM_LBUTTONUP, x, y, 0, 0);
|
|
}
|
|
|
|
if (but == 2 && down)
|
|
{
|
|
self->mm->mod->mod_event(self->mm->mod, WM_RBUTTONDOWN, x, y, 0, 0);
|
|
}
|
|
else if (but == 2 && !down)
|
|
{
|
|
self->mm->mod->mod_event(self->mm->mod, WM_RBUTTONUP, x, y, 0, 0);
|
|
}
|
|
|
|
if (but == 3 && down)
|
|
{
|
|
self->mm->mod->mod_event(self->mm->mod, WM_BUTTON3DOWN, x, y, 0, 0);
|
|
}
|
|
else if (but == 3 && !down)
|
|
{
|
|
self->mm->mod->mod_event(self->mm->mod, WM_BUTTON3UP, x, y, 0, 0);
|
|
}
|
|
|
|
if (but == 4)
|
|
{
|
|
self->mm->mod->mod_event(self->mm->mod, WM_BUTTON4DOWN,
|
|
self->mouse_x, self->mouse_y, 0, 0);
|
|
self->mm->mod->mod_event(self->mm->mod, WM_BUTTON4UP,
|
|
self->mouse_x, self->mouse_y, 0, 0);
|
|
}
|
|
|
|
if (but == 5)
|
|
{
|
|
self->mm->mod->mod_event(self->mm->mod, WM_BUTTON5DOWN,
|
|
self->mouse_x, self->mouse_y, 0, 0);
|
|
self->mm->mod->mod_event(self->mm->mod, WM_BUTTON5UP,
|
|
self->mouse_x, self->mouse_y, 0, 0);
|
|
}
|
|
if (but == 6 && down)
|
|
{
|
|
self->mm->mod->mod_event(self->mm->mod, WM_BUTTON6DOWN, x, y, 0, 0);
|
|
}
|
|
else if (but == 6 && !down)
|
|
{
|
|
self->mm->mod->mod_event(self->mm->mod, WM_BUTTON6UP, x, y, 0, 0);
|
|
}
|
|
if (but == 7 && down)
|
|
{
|
|
self->mm->mod->mod_event(self->mm->mod, WM_BUTTON7DOWN, x, y, 0, 0);
|
|
}
|
|
else if (but == 7 && !down)
|
|
{
|
|
self->mm->mod->mod_event(self->mm->mod, WM_BUTTON7UP, x, y, 0, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (self->popup_wnd != 0)
|
|
{
|
|
if (self->popup_wnd == control && !down)
|
|
{
|
|
xrdp_bitmap_def_proc(self->popup_wnd, WM_LBUTTONUP, x, y);
|
|
xrdp_wm_clear_popup(self);
|
|
self->button_down = 0;
|
|
return 0;
|
|
}
|
|
else if (self->popup_wnd != control && down)
|
|
{
|
|
xrdp_wm_clear_popup(self);
|
|
self->button_down = 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if (control != 0)
|
|
{
|
|
if (wnd != 0)
|
|
{
|
|
if (wnd->modal_dialog != 0) /* if window has a modal dialog */
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (control == wnd)
|
|
{
|
|
}
|
|
else if (control->tab_stop)
|
|
{
|
|
focus_out_control = wnd->focused_control;
|
|
wnd->focused_control = control;
|
|
xrdp_bitmap_invalidate(focus_out_control, 0);
|
|
xrdp_bitmap_invalidate(control, 0);
|
|
}
|
|
}
|
|
|
|
if ((control->type == WND_TYPE_BUTTON ||
|
|
control->type == WND_TYPE_COMBO) &&
|
|
but == 1 && !down && self->button_down == control)
|
|
{
|
|
/* if clicking up on a button that was clicked down */
|
|
self->button_down = 0;
|
|
control->state = 0;
|
|
xrdp_bitmap_invalidate(control, 0);
|
|
|
|
if (control->parent != 0)
|
|
{
|
|
if (control->parent->notify != 0)
|
|
{
|
|
/* control can be invalid after this */
|
|
control->parent->notify(control->owner, control, 1, x, y);
|
|
}
|
|
}
|
|
}
|
|
else if ((control->type == WND_TYPE_BUTTON ||
|
|
control->type == WND_TYPE_COMBO) &&
|
|
but == 1 && down)
|
|
{
|
|
/* if clicking down on a button or combo */
|
|
self->button_down = control;
|
|
control->state = 1;
|
|
xrdp_bitmap_invalidate(control, 0);
|
|
|
|
if (control->type == WND_TYPE_COMBO)
|
|
{
|
|
xrdp_wm_pu(self, control);
|
|
}
|
|
}
|
|
else if (but == 1 && down)
|
|
{
|
|
if (self->popup_wnd == 0)
|
|
{
|
|
xrdp_wm_set_focused(self, wnd);
|
|
|
|
if (control->type == WND_TYPE_WND && y < (control->top + 21))
|
|
{
|
|
/* if dragging */
|
|
if (self->dragging) /* rarely happens */
|
|
{
|
|
newx = self->draggingx - self->draggingdx;
|
|
newy = self->draggingy - self->draggingdy;
|
|
|
|
if (self->draggingxorstate)
|
|
{
|
|
xrdp_wm_xor_pat(self, newx, newy,
|
|
self->draggingcx, self->draggingcy);
|
|
}
|
|
|
|
self->draggingxorstate = 0;
|
|
}
|
|
|
|
self->dragging = 1;
|
|
self->dragging_window = control;
|
|
self->draggingorgx = control->left;
|
|
self->draggingorgy = control->top;
|
|
self->draggingx = x;
|
|
self->draggingy = y;
|
|
self->draggingdx = x - control->left;
|
|
self->draggingdy = y - control->top;
|
|
self->draggingcx = control->width;
|
|
self->draggingcy = control->height;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
xrdp_wm_set_focused(self, 0);
|
|
}
|
|
|
|
/* no matter what, mouse is up, reset button_down */
|
|
if (but == 1 && !down && self->button_down != 0)
|
|
{
|
|
self->button_down = 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
int APP_CC
|
|
xrdp_wm_key(struct xrdp_wm *self, int device_flags, int scan_code)
|
|
{
|
|
int msg;
|
|
struct xrdp_key_info *ki;
|
|
|
|
/*g_printf("count %d\n", self->key_down_list->count);*/
|
|
scan_code = scan_code % 128;
|
|
|
|
if (self->popup_wnd != 0)
|
|
{
|
|
xrdp_wm_clear_popup(self);
|
|
return 0;
|
|
}
|
|
|
|
if (device_flags & KBD_FLAG_UP) /* 0x8000 */
|
|
{
|
|
self->keys[scan_code] = 0;
|
|
msg = WM_KEYUP;
|
|
}
|
|
else /* key down */
|
|
{
|
|
self->keys[scan_code] = 1 | device_flags;
|
|
msg = WM_KEYDOWN;
|
|
|
|
switch (scan_code)
|
|
{
|
|
case 58:
|
|
self->caps_lock = !self->caps_lock;
|
|
break; /* caps lock */
|
|
case 69:
|
|
self->num_lock = !self->num_lock;
|
|
break; /* num lock */
|
|
case 70:
|
|
self->scroll_lock = !self->scroll_lock;
|
|
break; /* scroll lock */
|
|
}
|
|
}
|
|
|
|
if (self->mm->mod != 0)
|
|
{
|
|
if (self->mm->mod->mod_event != 0)
|
|
{
|
|
ki = get_key_info_from_scan_code
|
|
(device_flags, scan_code, self->keys, self->caps_lock,
|
|
self->num_lock, self->scroll_lock,
|
|
&(self->keymap));
|
|
|
|
if (ki != 0)
|
|
{
|
|
self->mm->mod->mod_event(self->mm->mod, msg, ki->chr, ki->sym,
|
|
scan_code, device_flags);
|
|
}
|
|
}
|
|
}
|
|
else if (self->focused_window != 0)
|
|
{
|
|
xrdp_bitmap_def_proc(self->focused_window,
|
|
msg, scan_code, device_flags);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* happens when client gets focus and sends key modifier info */
|
|
int APP_CC
|
|
xrdp_wm_key_sync(struct xrdp_wm *self, int device_flags, int key_flags)
|
|
{
|
|
self->num_lock = 0;
|
|
self->scroll_lock = 0;
|
|
self->caps_lock = 0;
|
|
|
|
if (key_flags & 1)
|
|
{
|
|
self->scroll_lock = 1;
|
|
}
|
|
|
|
if (key_flags & 2)
|
|
{
|
|
self->num_lock = 1;
|
|
}
|
|
|
|
if (key_flags & 4)
|
|
{
|
|
self->caps_lock = 1;
|
|
}
|
|
|
|
if (self->mm->mod != 0)
|
|
{
|
|
if (self->mm->mod->mod_event != 0)
|
|
{
|
|
self->mm->mod->mod_event(self->mm->mod, 17, key_flags, device_flags,
|
|
key_flags, device_flags);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
int APP_CC
|
|
xrdp_wm_pu(struct xrdp_wm *self, struct xrdp_bitmap *control)
|
|
{
|
|
int x;
|
|
int y;
|
|
|
|
if (self == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (control == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
self->popup_wnd = xrdp_bitmap_create(control->width, DEFAULT_WND_SPECIAL_H,
|
|
self->screen->bpp,
|
|
WND_TYPE_SPECIAL, self);
|
|
self->popup_wnd->popped_from = control;
|
|
self->popup_wnd->parent = self->screen;
|
|
self->popup_wnd->owner = self->screen;
|
|
x = xrdp_bitmap_to_screenx(control, 0);
|
|
y = xrdp_bitmap_to_screeny(control, 0);
|
|
self->popup_wnd->left = x;
|
|
self->popup_wnd->top = y + control->height;
|
|
self->popup_wnd->item_index = control->item_index;
|
|
list_insert_item(self->screen->child_list, 0, (long)self->popup_wnd);
|
|
xrdp_bitmap_invalidate(self->popup_wnd, 0);
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
static int APP_CC
|
|
xrdp_wm_process_input_mouse(struct xrdp_wm *self, int device_flags,
|
|
int x, int y)
|
|
{
|
|
DEBUG(("mouse event flags %4.4x x %d y %d", device_flags, x, y));
|
|
|
|
if (device_flags & MOUSE_FLAG_MOVE) /* 0x0800 */
|
|
{
|
|
xrdp_wm_mouse_move(self, x, y);
|
|
}
|
|
|
|
if (device_flags & MOUSE_FLAG_BUTTON1) /* 0x1000 */
|
|
{
|
|
if (device_flags & MOUSE_FLAG_DOWN) /* 0x8000 */
|
|
{
|
|
xrdp_wm_mouse_click(self, x, y, 1, 1);
|
|
}
|
|
else
|
|
{
|
|
xrdp_wm_mouse_click(self, x, y, 1, 0);
|
|
}
|
|
}
|
|
|
|
if (device_flags & MOUSE_FLAG_BUTTON2) /* 0x2000 */
|
|
{
|
|
if (device_flags & MOUSE_FLAG_DOWN) /* 0x8000 */
|
|
{
|
|
xrdp_wm_mouse_click(self, x, y, 2, 1);
|
|
}
|
|
else
|
|
{
|
|
xrdp_wm_mouse_click(self, x, y, 2, 0);
|
|
}
|
|
}
|
|
|
|
if (device_flags & MOUSE_FLAG_BUTTON3) /* 0x4000 */
|
|
{
|
|
if (device_flags & MOUSE_FLAG_DOWN) /* 0x8000 */
|
|
{
|
|
xrdp_wm_mouse_click(self, x, y, 3, 1);
|
|
}
|
|
else
|
|
{
|
|
xrdp_wm_mouse_click(self, x, y, 3, 0);
|
|
}
|
|
}
|
|
|
|
if (device_flags & 0x200) /* PTRFLAGS_WHEEL */
|
|
{
|
|
if (device_flags & 0x100) /* PTRFLAGS_WHEEL_NEGATIVE */
|
|
{
|
|
xrdp_wm_mouse_click(self, 0, 0, 5, 0);
|
|
}
|
|
else
|
|
{
|
|
xrdp_wm_mouse_click(self, 0, 0, 4, 0);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
static int APP_CC
|
|
xrdp_wm_process_input_mousex(struct xrdp_wm* self, int device_flags,
|
|
int x, int y)
|
|
{
|
|
if (device_flags & 0x8000) /* PTRXFLAGS_DOWN */
|
|
{
|
|
if (device_flags & 0x0001) /* PTRXFLAGS_BUTTON1 */
|
|
{
|
|
xrdp_wm_mouse_click(self, x, y, 6, 1);
|
|
}
|
|
else if (device_flags & 0x0002) /* PTRXFLAGS_BUTTON2 */
|
|
{
|
|
xrdp_wm_mouse_click(self, x, y, 7, 1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (device_flags & 0x0001) /* PTRXFLAGS_BUTTON1 */
|
|
{
|
|
xrdp_wm_mouse_click(self, x, y, 6, 0);
|
|
}
|
|
else if (device_flags & 0x0002) /* PTRXFLAGS_BUTTON2 */
|
|
{
|
|
xrdp_wm_mouse_click(self, x, y, 7, 0);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/* param1 = MAKELONG(channel_id, flags)
|
|
param2 = size
|
|
param3 = pointer to data
|
|
param4 = total size */
|
|
static int APP_CC
|
|
xrdp_wm_process_channel_data(struct xrdp_wm *self,
|
|
tbus param1, tbus param2,
|
|
tbus param3, tbus param4)
|
|
{
|
|
int rv;
|
|
int chanid ;
|
|
rv = 1;
|
|
|
|
if (self->mm->mod != 0)
|
|
{
|
|
chanid = LOWORD(param1);
|
|
|
|
if (is_channel_allowed(self, chanid))
|
|
{
|
|
if (self->mm->usechansrv)
|
|
{
|
|
rv = xrdp_mm_process_channel_data(self->mm, param1, param2,
|
|
param3, param4);
|
|
}
|
|
else
|
|
{
|
|
if (self->mm->mod->mod_event != 0)
|
|
{
|
|
rv = self->mm->mod->mod_event(self->mm->mod, 0x5555, param1, param2,
|
|
param3, param4);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/* this is the callbacks coming from libxrdp.so */
|
|
int DEFAULT_CC
|
|
callback(long id, int msg, long param1, long param2, long param3, long param4)
|
|
{
|
|
int rv;
|
|
struct xrdp_wm *wm;
|
|
struct xrdp_rect rect;
|
|
|
|
if (id == 0) /* "id" should be "struct xrdp_process*" as long */
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
wm = ((struct xrdp_process *)id)->wm;
|
|
|
|
if (wm == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
rv = 0;
|
|
|
|
switch (msg)
|
|
{
|
|
case 0: /* RDP_INPUT_SYNCHRONIZE */
|
|
rv = xrdp_wm_key_sync(wm, param3, param1);
|
|
break;
|
|
case 4: /* RDP_INPUT_SCANCODE */
|
|
rv = xrdp_wm_key(wm, param3, param1);
|
|
break;
|
|
case 0x8001: /* RDP_INPUT_MOUSE */
|
|
rv = xrdp_wm_process_input_mouse(wm, param3, param1, param2);
|
|
break;
|
|
case 0x8002: /* RDP_INPUT_MOUSEX (INPUT_EVENT_MOUSEX) */
|
|
rv = xrdp_wm_process_input_mousex(wm, param3, param1, param2);
|
|
break;
|
|
case 0x4444: /* invalidate, this is not from RDP_DATA_PDU_INPUT */
|
|
/* like the rest, its from RDP_PDU_DATA with code 33 */
|
|
/* its the rdp client asking for a screen update */
|
|
MAKERECT(rect, param1, param2, param3, param4);
|
|
rv = xrdp_bitmap_invalidate(wm->screen, &rect);
|
|
break;
|
|
case 0x5555: /* called from xrdp_channel.c, channel data has come in,
|
|
pass it to module if there is one */
|
|
rv = xrdp_wm_process_channel_data(wm, param1, param2, param3, param4);
|
|
break;
|
|
case 0x5556:
|
|
rv = xrdp_mm_check_chan(wm->mm);
|
|
break;
|
|
case 0x5557:
|
|
//g_writeln("callback: frame ack %d", param1);
|
|
xrdp_mm_frame_ack(wm->mm, param1);
|
|
break;
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/* returns error */
|
|
/* this gets called when there is nothing on any socket */
|
|
static int APP_CC
|
|
xrdp_wm_login_mode_changed(struct xrdp_wm *self)
|
|
{
|
|
if (self == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
g_writeln("xrdp_wm_login_mode_changed: login_mode is %d", self->login_mode);
|
|
|
|
if (self->login_mode == 0)
|
|
{
|
|
/* this is the initial state of the login window */
|
|
xrdp_wm_set_login_mode(self, 1); /* put the wm in login mode */
|
|
list_clear(self->log);
|
|
xrdp_wm_delete_all_children(self);
|
|
self->dragging = 0;
|
|
xrdp_wm_init(self);
|
|
}
|
|
else if (self->login_mode == 2)
|
|
{
|
|
if (xrdp_mm_connect(self->mm) == 0)
|
|
{
|
|
xrdp_wm_set_login_mode(self, 3); /* put the wm in connected mode */
|
|
xrdp_wm_delete_all_children(self);
|
|
self->dragging = 0;
|
|
}
|
|
else
|
|
{
|
|
/* we do nothing on connect error so far */
|
|
}
|
|
}
|
|
else if (self->login_mode == 10)
|
|
{
|
|
xrdp_wm_delete_all_children(self);
|
|
self->dragging = 0;
|
|
xrdp_wm_set_login_mode(self, 11);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* this is the log windows notify function */
|
|
static int DEFAULT_CC
|
|
xrdp_wm_log_wnd_notify(struct xrdp_bitmap *wnd,
|
|
struct xrdp_bitmap *sender,
|
|
int msg, long param1, long param2)
|
|
{
|
|
struct xrdp_painter *painter;
|
|
struct xrdp_wm *wm;
|
|
struct xrdp_rect rect;
|
|
int index;
|
|
char *text;
|
|
|
|
if (wnd == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (sender == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (wnd->owner == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
wm = wnd->wm;
|
|
|
|
if (msg == 1) /* click */
|
|
{
|
|
if (sender->id == 1) /* ok button */
|
|
{
|
|
/* close the log window */
|
|
MAKERECT(rect, wnd->left, wnd->top, wnd->width, wnd->height);
|
|
xrdp_bitmap_delete(wnd);
|
|
xrdp_bitmap_invalidate(wm->screen, &rect);
|
|
|
|
/* if module is gone, reset the session when ok is clicked */
|
|
if (wm->mm->mod_handle == 0)
|
|
{
|
|
/* make sure autologin is off */
|
|
wm->session->client_info->rdp_autologin = 0;
|
|
xrdp_wm_set_login_mode(wm, 0); /* reset session */
|
|
}
|
|
}
|
|
}
|
|
else if (msg == WM_PAINT) /* 3 */
|
|
{
|
|
painter = (struct xrdp_painter *)param1;
|
|
|
|
if (painter != 0)
|
|
{
|
|
painter->fg_color = wnd->wm->black;
|
|
|
|
for (index = 0; index < wnd->wm->log->count; index++)
|
|
{
|
|
text = (char *)list_get_item(wnd->wm->log, index);
|
|
xrdp_painter_draw_text(painter, wnd, 10, 30 + index * 15, text);
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void add_string_to_logwindow(char *msg, struct list *log)
|
|
{
|
|
|
|
char *new_part_message;
|
|
char *current_pointer = msg ;
|
|
int processedlen = 0;
|
|
|
|
do
|
|
{
|
|
new_part_message = g_strndup(current_pointer, LOG_WINDOW_CHAR_PER_LINE) ;
|
|
g_writeln("%s",new_part_message);
|
|
list_add_item(log, (long)new_part_message);
|
|
processedlen = processedlen + g_strlen(new_part_message);
|
|
current_pointer = current_pointer + g_strlen(new_part_message) ;
|
|
}
|
|
while ((processedlen < g_strlen(msg)) && (processedlen < DEFAULT_STRING_LEN));
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
int APP_CC
|
|
xrdp_wm_show_log(struct xrdp_wm *self)
|
|
{
|
|
struct xrdp_bitmap *but;
|
|
int w;
|
|
int h;
|
|
int xoffset;
|
|
int yoffset;
|
|
int index;
|
|
int primary_x_offset;
|
|
int primary_y_offset;
|
|
|
|
|
|
if (self->hide_log_window)
|
|
{
|
|
/* make sure autologin is off */
|
|
self->session->client_info->rdp_autologin = 0;
|
|
xrdp_wm_set_login_mode(self, 0); /* reset session */
|
|
return 0;
|
|
}
|
|
|
|
if (self->log_wnd == 0)
|
|
{
|
|
w = DEFAULT_WND_LOG_W;
|
|
h = DEFAULT_WND_LOG_H;
|
|
xoffset = 10;
|
|
yoffset = 10;
|
|
|
|
if (self->screen->width < w)
|
|
{
|
|
w = self->screen->width - 4;
|
|
xoffset = 2;
|
|
}
|
|
|
|
if (self->screen->height < h)
|
|
{
|
|
h = self->screen->height - 4;
|
|
yoffset = 2;
|
|
}
|
|
|
|
primary_x_offset = 0;
|
|
primary_y_offset = 0;
|
|
|
|
/* multimon scenario, draw log window on primary monitor */
|
|
if (self->client_info->monitorCount > 1)
|
|
{
|
|
for (index = 0; index < self->client_info->monitorCount; index++)
|
|
{
|
|
if (self->client_info->minfo_wm[index].is_primary)
|
|
{
|
|
primary_x_offset = self->client_info->minfo_wm[index].left;
|
|
primary_y_offset = self->client_info->minfo_wm[index].top;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* log window */
|
|
self->log_wnd = xrdp_bitmap_create(w, h, self->screen->bpp,
|
|
WND_TYPE_WND, self);
|
|
list_add_item(self->screen->child_list, (long)self->log_wnd);
|
|
self->log_wnd->parent = self->screen;
|
|
self->log_wnd->owner = self->screen;
|
|
self->log_wnd->bg_color = self->grey;
|
|
self->log_wnd->left = primary_x_offset + xoffset;
|
|
self->log_wnd->top = primary_y_offset + yoffset;
|
|
set_string(&(self->log_wnd->caption1), "Connection Log");
|
|
/* ok button */
|
|
but = xrdp_bitmap_create(DEFAULT_BUTTON_W, DEFAULT_BUTTON_H, self->screen->bpp, WND_TYPE_BUTTON, self);
|
|
list_insert_item(self->log_wnd->child_list, 0, (long)but);
|
|
but->parent = self->log_wnd;
|
|
but->owner = self->log_wnd;
|
|
but->left = (w - DEFAULT_BUTTON_W) - xoffset;
|
|
but->top = (h - DEFAULT_BUTTON_H) - yoffset;
|
|
but->id = 1;
|
|
but->tab_stop = 1;
|
|
set_string(&but->caption1, "OK");
|
|
self->log_wnd->focused_control = but;
|
|
/* set notify function */
|
|
self->log_wnd->notify = xrdp_wm_log_wnd_notify;
|
|
}
|
|
|
|
xrdp_wm_set_focused(self, self->log_wnd);
|
|
xrdp_bitmap_invalidate(self->log_wnd, 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
int APP_CC
|
|
xrdp_wm_log_msg(struct xrdp_wm *self, char *msg)
|
|
{
|
|
add_string_to_logwindow(msg, self->log);
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
int APP_CC
|
|
xrdp_wm_get_wait_objs(struct xrdp_wm *self, tbus *robjs, int *rc,
|
|
tbus *wobjs, int *wc, int *timeout)
|
|
{
|
|
int i;
|
|
|
|
if (self == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
i = *rc;
|
|
robjs[i++] = self->login_mode_event;
|
|
*rc = i;
|
|
return xrdp_mm_get_wait_objs(self->mm, robjs, rc, wobjs, wc, timeout);
|
|
}
|
|
|
|
/******************************************************************************/
|
|
int APP_CC
|
|
xrdp_wm_check_wait_objs(struct xrdp_wm *self)
|
|
{
|
|
int rv;
|
|
|
|
if (self == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
rv = 0;
|
|
|
|
if (g_is_wait_obj_set(self->login_mode_event))
|
|
{
|
|
g_reset_wait_obj(self->login_mode_event);
|
|
xrdp_wm_login_mode_changed(self);
|
|
}
|
|
|
|
if (rv == 0)
|
|
{
|
|
rv = xrdp_mm_check_wait_objs(self->mm);
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
int APP_CC
|
|
xrdp_wm_set_login_mode(struct xrdp_wm *self, int login_mode)
|
|
{
|
|
self->login_mode = login_mode;
|
|
g_set_wait_obj(self->login_mode_event);
|
|
return 0;
|
|
}
|