implemented floatbar for x11

This commit is contained in:
Markus Mattes 2018-09-18 21:25:51 +02:00
parent 5a154dccbd
commit 21e4804a7f
21 changed files with 851 additions and 6 deletions

3
.gitignore vendored
View File

@ -140,3 +140,6 @@ packaging/deb/freerdp-nightly/freerdp-nightly-dbg
#
.idea
# VisualStudio Code
.vscode

View File

@ -217,6 +217,7 @@ static BOOL wf_pre_connect(freerdp* instance)
settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE;
settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE;
wfc->fullscreen = settings->Fullscreen;
wfc->floatbar_active = settings->Floatbar;
if (wfc->fullscreen)
wfc->fs_toggle = 1;

View File

@ -80,6 +80,7 @@ struct wf_context
int offset_y;
int fs_toggle;
int fullscreen;
int floatbar_active;
int percentscreen;
char window_title[64];
int client_x;

View File

@ -404,7 +404,7 @@ void wf_toggle_fullscreen(wfContext* wfc)
wfc->disablewindowtracking = TRUE;
}
if (wfc->fullscreen)
if (wfc->fullscreen && wfc->floatbar_active)
floatbar_show(wfc->floatbar);
else
floatbar_hide(wfc->floatbar);

View File

@ -36,6 +36,8 @@ set(${MODULE_PREFIX}_SRCS
xf_input.h
xf_event.c
xf_event.h
xf_floatbar.c
xf_floatbar.h
xf_input.c
xf_input.h
xf_channels.c

View File

@ -0,0 +1,11 @@
#define close_width 24
#define close_height 24
static unsigned char close_bits[] =
{
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x7c, 0xfe, 0xff, 0x38, 0xfe, 0xff, 0x11, 0xff, 0xff, 0x83, 0xff,
0xff, 0xc7, 0xff, 0xff, 0x83, 0xff, 0xff, 0x11, 0xff, 0xff, 0x38, 0xfe,
0xff, 0x7c, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};

View File

@ -0,0 +1,11 @@
#define lock_width 24
#define lock_height 24
static unsigned char lock_bits[] =
{
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x83, 0xff,
0xff, 0x83, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xc7, 0xff,
0xff, 0x00, 0xfe, 0xff, 0x00, 0xfe, 0xff, 0xef, 0xff, 0xff, 0xef, 0xff,
0xff, 0xef, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};

View File

@ -0,0 +1,11 @@
#define minimize_width 24
#define minimize_height 24
static unsigned char minimize_bits[] =
{
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xfc,
0x3f, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};

View File

@ -0,0 +1,11 @@
#define restore_width 24
#define restore_height 24
static unsigned char restore_bits[] =
{
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x03, 0xff, 0xff, 0x03, 0xff, 0xff, 0x3b, 0xff, 0x7f, 0x20, 0xff,
0x7f, 0x20, 0xff, 0x7f, 0x07, 0xff, 0x7f, 0xe7, 0xff, 0x7f, 0xe7, 0xff,
0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};

View File

@ -0,0 +1,11 @@
#define unlock_width 24
#define unlock_height 24
static unsigned char unlock_bits[] =
{
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xf3, 0xff, 0xff, 0xf3, 0xff, 0xff, 0x73, 0xfe, 0xff, 0x03, 0xfe,
0x3f, 0x00, 0xfe, 0xff, 0x03, 0xfe, 0xff, 0x73, 0xfe, 0xff, 0xf3, 0xff,
0xff, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};

View File

@ -1182,6 +1182,7 @@ static BOOL xf_pre_connect(freerdp* instance)
xfc->decorations = settings->Decorations;
xfc->grab_keyboard = settings->GrabKeyboard;
xfc->fullscreen_toggle = settings->ToggleFullscreen;
xfc->floatbar = settings->Floatbar;
xf_button_map_init(xfc);
return TRUE;
}
@ -1581,6 +1582,9 @@ static DWORD WINAPI xf_client_thread(LPVOID param)
nCount += tmp;
}
if (xfc->floatbar && xfc->fullscreen)
xf_floatbar_hide_and_show(xfc);
waitStatus = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE);
if (waitStatus == WAIT_FAILED)

View File

@ -366,6 +366,9 @@ static BOOL xf_event_MotionNotify(xfContext* xfc, XEvent* event, BOOL app)
if (xfc->use_xinput)
return TRUE;
if(xfc->floatbar && !(app))
xf_floatbar_set_root_y(xfc, event->xmotion.y);
return xf_generic_MotionNotify(xfc, event->xmotion.x, event->xmotion.y,
event->xmotion.state, event->xmotion.window, app);
}
@ -1014,6 +1017,12 @@ BOOL xf_event_process(freerdp* instance, XEvent* event)
}
}
if (xfc->floatbar && xf_floatbar_check_event(xfc, event))
{
xf_floatbar_event_process(xfc, event);
return TRUE;
}
xf_event_execute_action_script(xfc, event);
if (event->type != MotionNotify)

711
client/X11/xf_floatbar.c Normal file
View File

@ -0,0 +1,711 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* X11 Windows
*
* Licensed under the Apache License, Version 2.0 (the "License");n
* 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.
*/
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/extensions/shape.h>
#include <X11/extensions/Xfixes.h>
#include <X11/cursorfont.h>
#include "xf_floatbar.h"
#include "resource/close.xbm"
#include "resource/lock.xbm"
#include "resource/unlock.xbm"
#include "resource/minimize.xbm"
#include "resource/restore.xbm"
#define TAG CLIENT_TAG("x11")
#define FLOATBAR_HEIGHT 26
#define FLOATBAR_DEFAULT_WIDTH 576
#define FLOATBAR_MIN_WIDTH 200
#define FLOATBAR_BORDER 24
#define FLOATBAR_BUTTON_WIDTH 24
#define FLOATBAR_COLOR_BACKGROUND "RGB:31/6c/a9"
#define FLOATBAR_COLOR_BORDER "RGB:75/9a/c8"
#define FLOATBAR_COLOR_FOREGROUND "RGB:FF/FF/FF"
#ifdef WITH_DEBUG_X11
#define DEBUG_X11(...) WLog_DBG(TAG, __VA_ARGS__)
#else
#define DEBUG_X11(...) do { } while (0)
#endif
#define XF_FLOATBAR_MODE_NONE 0
#define XF_FLOATBAR_MODE_DRAGGING 1
#define XF_FLOATBAR_MODE_RESIZE_LEFT 2
#define XF_FLOATBAR_MODE_RESIZE_RIGHT 3
#define XF_FLOATBAR_BUTTON_CLOSE 1
#define XF_FLOATBAR_BUTTON_RESTORE 2
#define XF_FLOATBAR_BUTTON_MINIMIZE 3
#define XF_FLOATBAR_BUTTON_LOCKED 4
typedef struct xf_floatbar_button xfFloatbarButton;
struct xf_floatbar
{
int x;
int y;
int width;
int height;
int mode;
int last_motion_x_root;
int last_motion_y_root;
bool locked;
xfFloatbarButton* buttons[4];
Window handle;
};
struct xf_floatbar_button
{
int x;
int y;
int type;
bool focus;
bool clicked;
OnClick onclick;
Window handle;
};
static void xf_floatbar_button_onclick_close(xfContext* xfc)
{
ExitProcess(EXIT_SUCCESS);
}
static void xf_floatbar_button_onclick_minimize(xfContext* xfc)
{
xf_SetWindowMinimized(xfc, xfc->window);
}
static void xf_floatbar_button_onclick_restore(xfContext* xfc)
{
xf_toggle_fullscreen(xfc);
}
static void xf_floatbar_button_onclick_locked(xfContext* xfc)
{
xfFloatbar* floatbar;
floatbar = xfc->window->floatbar;
floatbar->locked = (floatbar->locked) ? FALSE : TRUE;
}
void xf_floatbar_set_root_y(xfContext* xfc, int y)
{
xfFloatbar* floatbar;
floatbar = xfc->window->floatbar;
floatbar->last_motion_y_root = y;
}
void xf_floatbar_hide_and_show(xfContext* xfc)
{
xfFloatbar* floatbar;
floatbar = xfc->window->floatbar;
if (!floatbar->locked)
{
if ((floatbar->mode == 0) && (floatbar->last_motion_y_root > 10) &&
(floatbar->y > (FLOATBAR_HEIGHT * -1)))
{
floatbar->y = floatbar->y - 1;
XMoveWindow(xfc->display, floatbar->handle, floatbar->x, floatbar->y);
}
else if (floatbar->y < 0)
{
floatbar->y = floatbar->y + 1;
XMoveWindow(xfc->display, floatbar->handle, floatbar->x, floatbar->y);
}
}
}
void xf_floatbar_toggle_visibility(xfContext* xfc, bool visible)
{
xfFloatbar* floatbar;
int i, size;
floatbar = xfc->window->floatbar;
if (visible)
{
XMapWindow(xfc->display, floatbar->handle);
size = ARRAYSIZE(floatbar->buttons);
for (i = 0; i < size; i++)
{
XMapWindow(xfc->display, floatbar->buttons[i]->handle);
}
}
else
{
XUnmapSubwindows(xfc->display, floatbar->handle);
XUnmapWindow(xfc->display, floatbar->handle);
}
}
static xfFloatbarButton* xf_floatbar_new_button(xfContext* xfc, xfFloatbar* floatbar, int type)
{
xfFloatbarButton* button;
button = (xfFloatbarButton*) calloc(1, sizeof(xfFloatbarButton));
button->type = type;
switch (type)
{
case XF_FLOATBAR_BUTTON_CLOSE:
button->x = floatbar->width - FLOATBAR_BORDER - FLOATBAR_BUTTON_WIDTH * type;
button->onclick = xf_floatbar_button_onclick_close;
break;
case XF_FLOATBAR_BUTTON_RESTORE:
button->x = floatbar->width - FLOATBAR_BORDER - FLOATBAR_BUTTON_WIDTH * type;
button->onclick = xf_floatbar_button_onclick_restore;
break;
case XF_FLOATBAR_BUTTON_MINIMIZE:
button->x = floatbar->width - FLOATBAR_BORDER - FLOATBAR_BUTTON_WIDTH * type;
button->onclick = xf_floatbar_button_onclick_minimize;
break;
case XF_FLOATBAR_BUTTON_LOCKED:
button->x = FLOATBAR_BORDER;
button->onclick = xf_floatbar_button_onclick_locked;
break;
default:
break;
}
button->y = 0;
button->focus = FALSE;
button->handle = XCreateWindow(xfc->display, floatbar->handle, button->x, 0, FLOATBAR_BUTTON_WIDTH,
FLOATBAR_BUTTON_WIDTH, 0, CopyFromParent, InputOutput, CopyFromParent, 0, NULL);
XSelectInput(xfc->display, button->handle, ExposureMask | ButtonPressMask | ButtonReleaseMask |
FocusChangeMask | LeaveWindowMask | EnterWindowMask | StructureNotifyMask);
return button;
}
xfFloatbar* xf_floatbar_new(xfContext* xfc, Window window)
{
xfFloatbar* floatbar;
XWindowAttributes attr;
int i, width;
floatbar = (xfFloatbar*) calloc(1, sizeof(xfFloatbar));
floatbar->locked = TRUE;
XGetWindowAttributes(xfc->display, window, &attr);
for(i = 0; i < xfc->vscreen.nmonitors; i++)
{
if(attr.x >= xfc->vscreen.monitors[i].area.left && attr.x <= xfc->vscreen.monitors[i].area.right)
{
width = xfc->vscreen.monitors[i].area.right - xfc->vscreen.monitors[i].area.left;
floatbar->x = width / 2 + xfc->vscreen.monitors[i].area.left - FLOATBAR_DEFAULT_WIDTH / 2;
}
}
floatbar->y = 0;
floatbar->handle = XCreateWindow(xfc->display, window, floatbar->x, 0, FLOATBAR_DEFAULT_WIDTH,
FLOATBAR_HEIGHT, 0,
CopyFromParent, InputOutput, CopyFromParent, 0, NULL);
floatbar->width = FLOATBAR_DEFAULT_WIDTH;
floatbar->height = FLOATBAR_HEIGHT;
floatbar->mode = XF_FLOATBAR_MODE_NONE;
floatbar->buttons[0] = xf_floatbar_new_button(xfc, floatbar, XF_FLOATBAR_BUTTON_CLOSE);
floatbar->buttons[1] = xf_floatbar_new_button(xfc, floatbar, XF_FLOATBAR_BUTTON_RESTORE);
floatbar->buttons[2] = xf_floatbar_new_button(xfc, floatbar, XF_FLOATBAR_BUTTON_MINIMIZE);
floatbar->buttons[3] = xf_floatbar_new_button(xfc, floatbar, XF_FLOATBAR_BUTTON_LOCKED);
XSelectInput(xfc->display, floatbar->handle, ExposureMask | ButtonPressMask | ButtonReleaseMask |
PointerMotionMask | FocusChangeMask | LeaveWindowMask | EnterWindowMask | StructureNotifyMask |
PropertyChangeMask);
return floatbar;
}
static unsigned long xf_floatbar_get_color(xfContext* xfc, char* rgb_value)
{
Colormap cmap;
XColor color;
cmap = DefaultColormap(xfc->display, XDefaultScreen(xfc->display));
XParseColor(xfc->display, cmap, rgb_value, &color);
XAllocColor(xfc->display, cmap, &color);
XFreeColormap(xfc->display, cmap);
return color.pixel;
}
static void xf_floatbar_event_expose(xfContext* xfc, XEvent* event)
{
GC gc, shape_gc;
Pixmap pmap;
XPoint shape[5], border[5];
xfFloatbar* floatbar;
int len;
floatbar = xfc->window->floatbar;
/* create the pixmap that we'll use for shaping the window */
pmap = XCreatePixmap(xfc->display, floatbar->handle, floatbar->width, floatbar->height, 1);
gc = XCreateGC(xfc->display, floatbar->handle, 0, 0);
shape_gc = XCreateGC(xfc->display, pmap, 0, 0);
/* points for drawing the floatbar */
shape[0].x = 0;
shape[0].y = 0;
shape[1].x = floatbar->width;
shape[1].y = 0;
shape[2].x = shape[1].x - FLOATBAR_BORDER;
shape[2].y = FLOATBAR_HEIGHT;
shape[3].x = shape[0].x + FLOATBAR_BORDER;
shape[3].y = FLOATBAR_HEIGHT;
shape[4].x = shape[0].x;
shape[4].y = shape[0].y;
/* points for drawing the border of the floatbar */
border[0].x = shape[0].x;
border[0].y = shape[0].y - 1;
border[1].x = shape[1].x - 1;
border[1].y = shape[1].y - 1;
border[2].x = shape[2].x;
border[2].y = shape[2].y - 1;
border[3].x = shape[3].x - 1;
border[3].y = shape[3].y - 1;
border[4].x = border[0].x;
border[4].y = border[0].y;
/* Fill all pixels with 0 */
XSetForeground(xfc->display, shape_gc, 0);
XFillRectangle(xfc->display, pmap, shape_gc, 0, 0, floatbar->width,
floatbar->height);
/* Fill all pixels which should be shown with 1 */
XSetForeground(xfc->display, shape_gc, 1);
XFillPolygon(xfc->display, pmap, shape_gc, shape, 5, 0, CoordModeOrigin);
XShapeCombineMask(xfc->display, floatbar->handle, ShapeBounding, 0, 0, pmap, ShapeSet);
/* draw the float bar */
XSetForeground(xfc->display, gc, xf_floatbar_get_color(xfc, FLOATBAR_COLOR_BACKGROUND));
XFillPolygon(xfc->display, floatbar->handle, gc, shape, 4, 0, CoordModeOrigin);
/* draw an border for the floatbar */
XSetForeground(xfc->display, gc, xf_floatbar_get_color(xfc, FLOATBAR_COLOR_BORDER));
XDrawLines(xfc->display, floatbar->handle, gc, border, 5, CoordModeOrigin);
/* draw the host name connected to */
len = strlen(xfc->context.settings->ServerHostname);
XSetForeground(xfc->display, gc, xf_floatbar_get_color(xfc, FLOATBAR_COLOR_FOREGROUND));
XDrawString(xfc->display, floatbar->handle, gc, floatbar->width / 2 - len * 2, 15,
xfc->context.settings->ServerHostname, len);
}
static xfFloatbarButton* xf_floatbar_get_button(xfContext* xfc, XEvent* event)
{
xfFloatbar* floatbar;
int i, size;
size = ARRAYSIZE(floatbar->buttons);
floatbar = xfc->window->floatbar;
for (i = 0; i < size; i++)
{
if (floatbar->buttons[i]->handle == event->xany.window)
{
return floatbar->buttons[i];
}
}
return NULL;
}
static void xf_floatbar_button_update_positon(xfContext* xfc, XEvent* event)
{
xfFloatbar* floatbar;
xfFloatbarButton* button;
int i, size;
floatbar = xfc->window->floatbar;
size = ARRAYSIZE(floatbar->buttons);
for (i = 0; i < size; i++)
{
button = floatbar->buttons[i];
switch (button->type)
{
case XF_FLOATBAR_BUTTON_CLOSE:
button->x = floatbar->width - FLOATBAR_BORDER - FLOATBAR_BUTTON_WIDTH * button->type;
break;
case XF_FLOATBAR_BUTTON_RESTORE:
button->x = floatbar->width - FLOATBAR_BORDER - FLOATBAR_BUTTON_WIDTH * button->type;
break;
case XF_FLOATBAR_BUTTON_MINIMIZE:
button->x = floatbar->width - FLOATBAR_BORDER - FLOATBAR_BUTTON_WIDTH * button->type;
break;
default:
break;
}
XMoveWindow(xfc->display, button->handle, button->x, button->y);
xf_floatbar_event_expose(xfc, event);
}
}
static void xf_floatbar_button_event_expose(xfContext* xfc, XEvent* event)
{
xfFloatbar* floatbar;
xfFloatbarButton* button;
static unsigned char* bits;
GC gc;
Pixmap pattern;
button = xf_floatbar_get_button(xfc, event);
if (!button)
return;
gc = XCreateGC(xfc->display, button->handle, 0, 0);
floatbar = xfc->window->floatbar;
switch (button->type)
{
case XF_FLOATBAR_BUTTON_CLOSE:
bits = close_bits;
break;
case XF_FLOATBAR_BUTTON_RESTORE:
bits = restore_bits;
break;
case XF_FLOATBAR_BUTTON_MINIMIZE:
bits = minimize_bits;
break;
case XF_FLOATBAR_BUTTON_LOCKED:
if (floatbar->locked)
bits = lock_bits;
else
bits = unlock_bits;
break;
default:
break;
}
pattern = XCreateBitmapFromData(xfc->display, button->handle, (const char*)bits,
FLOATBAR_BUTTON_WIDTH, FLOATBAR_BUTTON_WIDTH);
if (!(button->focus))
XSetForeground(xfc->display, gc, xf_floatbar_get_color(xfc, FLOATBAR_COLOR_BACKGROUND));
else
XSetForeground(xfc->display, gc, xf_floatbar_get_color(xfc, FLOATBAR_COLOR_BORDER));
XSetBackground(xfc->display, gc, xf_floatbar_get_color(xfc, FLOATBAR_COLOR_FOREGROUND));
XCopyPlane(xfc->display, pattern, button->handle, gc, 0, 0, FLOATBAR_BUTTON_WIDTH,
FLOATBAR_BUTTON_WIDTH, 0, 0, 1);
XFreePixmap(xfc->display, pattern);
XFreeGC(xfc->display, gc);
}
static void xf_floatbar_button_event_buttonpress(xfContext* xfc, XEvent* event)
{
xfFloatbarButton* button;
button = xf_floatbar_get_button(xfc, event);
if (button)
button->clicked = TRUE;
}
static void xf_floatbar_button_event_buttonrelease(xfContext* xfc, XEvent* event)
{
xfFloatbarButton* button;
button = xf_floatbar_get_button(xfc, event);
if (button)
{
if (button->clicked)
button->onclick(xfc);
}
}
static void xf_floatbar_event_buttonpress(xfContext* xfc, XEvent* event)
{
xfFloatbar* floatbar;
floatbar = xfc->window->floatbar;
switch (event->xbutton.button)
{
case Button1:
if (event->xmotion.x <= FLOATBAR_BORDER)
floatbar->mode = XF_FLOATBAR_MODE_RESIZE_LEFT;
else if (event->xmotion.x >= (floatbar->width - FLOATBAR_BORDER))
floatbar->mode = XF_FLOATBAR_MODE_RESIZE_RIGHT;
else
floatbar->mode = XF_FLOATBAR_MODE_DRAGGING;
break;
default:
break;
}
}
static void xf_floatbar_event_buttonrelease(xfContext* xfc, XEvent* event)
{
switch (event->xbutton.button)
{
case Button1:
xfc->window->floatbar->mode = XF_FLOATBAR_MODE_NONE;
break;
default:
break;
}
}
static void xf_floatbar_resize(xfContext* xfc, XEvent* event)
{
xfFloatbar* floatbar;
floatbar = xfc->window->floatbar;
int x, width, movement;
/* calculate movement which happened on the root window */
movement = event->xmotion.x_root - floatbar->last_motion_x_root;
/* set x and width depending if movement happens on the left or right */
if (floatbar->mode == XF_FLOATBAR_MODE_RESIZE_LEFT)
{
x = floatbar->x + movement;
width = floatbar->width + movement * -1;
}
else
{
x = floatbar->x;
width = floatbar->width + movement;
}
/* only resize and move window if still above minimum width */
if (FLOATBAR_MIN_WIDTH < width)
{
XMoveResizeWindow(xfc->display, floatbar->handle, x, 0, width, floatbar->height);
floatbar->x = x;
floatbar->width = width;
}
}
static void xf_floatbar_dragging(xfContext* xfc, XEvent* event)
{
xfFloatbar* floatbar;
floatbar = xfc->window->floatbar;
int x, movement;
/* calculate movement and new x position */
movement = event->xmotion.x_root - floatbar->last_motion_x_root;
x = floatbar->x + movement;
/* do nothing if floatbar would be moved out of the window */
if (x < 0 || (x + floatbar->width) > xfc->window->width)
return;
/* move window to new x position */
XMoveWindow(xfc->display, floatbar->handle, x, 0);
/* update struct values for the next event */
floatbar->last_motion_x_root = floatbar->last_motion_x_root + movement;
floatbar->x = x;
}
static void xf_floatbar_event_motionnotify(xfContext* xfc, XEvent* event)
{
int mode;
xfFloatbar* floatbar;
Cursor cursor;
mode = xfc->window->floatbar->mode;
floatbar = xfc->window->floatbar;
cursor = XCreateFontCursor(xfc->display, XC_arrow);
if (event->xmotion.state && Button1Mask && mode > XF_FLOATBAR_MODE_DRAGGING)
{
xf_floatbar_resize(xfc, event);
}
else if (event->xmotion.state && Button1Mask && mode == XF_FLOATBAR_MODE_DRAGGING)
{
xf_floatbar_dragging(xfc, event);
}
else
{
if (event->xmotion.x <= FLOATBAR_BORDER ||
event->xmotion.x >= xfc->window->floatbar->width - FLOATBAR_BORDER)
cursor = XCreateFontCursor(xfc->display, XC_sb_h_double_arrow);
}
XDefineCursor(xfc->display, xfc->window->handle, cursor);
XFreeCursor(xfc->display, cursor);
xfc->window->floatbar->last_motion_x_root = event->xmotion.x_root;
}
static void xf_floatbar_button_event_focusin(xfContext* xfc, XEvent* event)
{
xfFloatbarButton* button;
button = xf_floatbar_get_button(xfc, event);
if (button)
{
button->focus = TRUE;
xf_floatbar_button_event_expose(xfc, event);
}
}
static void xf_floatbar_button_event_focusout(xfContext* xfc, XEvent* event)
{
xfFloatbarButton* button;
button = xf_floatbar_get_button(xfc, event);
if (button)
{
button->focus = FALSE;
button->clicked = FALSE;
xf_floatbar_button_event_expose(xfc, event);
}
}
static void xf_floatbar_event_focusout(xfContext* xfc, XEvent* event)
{
Cursor cursor;
cursor = XCreateFontCursor(xfc->display, XC_arrow);
XDefineCursor(xfc->display, xfc->window->handle, cursor);
XFreeCursor(xfc->display, cursor);
}
BOOL xf_floatbar_check_event(xfContext* xfc, XEvent* event)
{
xfFloatbar* floatbar;
xfFloatbarButton* button;
int i, size;
floatbar = xfc->window->floatbar;
if (event->xany.window == floatbar->handle)
return TRUE;
size = ARRAYSIZE(floatbar->buttons);
for (i = 0; i < size; i++)
{
button = floatbar->buttons[i];
if (event->xany.window == button->handle)
return TRUE;
}
return FALSE;
}
BOOL xf_floatbar_event_process(xfContext* xfc, XEvent* event)
{
xfFloatbar* floatbar;
floatbar = xfc->window->floatbar;
switch (event->type)
{
case Expose:
if (event->xany.window == floatbar->handle)
xf_floatbar_event_expose(xfc, event);
else
xf_floatbar_button_event_expose(xfc, event);
break;
case MotionNotify:
xf_floatbar_event_motionnotify(xfc, event);
break;
case ButtonPress:
if (event->xany.window == floatbar->handle)
xf_floatbar_event_buttonpress(xfc, event);
else
xf_floatbar_button_event_buttonpress(xfc, event);
break;
case ButtonRelease:
if (event->xany.window == floatbar->handle)
xf_floatbar_event_buttonrelease(xfc, event);
else
xf_floatbar_button_event_buttonrelease(xfc, event);
break;
case EnterNotify:
case FocusIn:
if (event->xany.window != floatbar->handle)
xf_floatbar_button_event_focusin(xfc, event);
break;
case LeaveNotify:
case FocusOut:
if (event->xany.window == floatbar->handle)
xf_floatbar_event_focusout(xfc, event);
else
xf_floatbar_button_event_focusout(xfc, event);
break;
case ConfigureNotify:
if (event->xany.window == floatbar->handle)
xf_floatbar_button_update_positon(xfc, event);
break;
case PropertyNotify:
if (event->xany.window == floatbar->handle)
xf_floatbar_button_update_positon(xfc, event);
break;
default:
break;
}
return floatbar->handle == event->xany.window;
}
static void xf_floatbar_button_free(xfContext* xfc, xfFloatbarButton* button)
{
if (!button)
return;
if (button->handle)
{
XUnmapWindow(xfc->display, button->handle);
XDestroyWindow(xfc->display, button->handle);
}
free(button);
}
void xf_floatbar_free(xfContext* xfc, xfWindow* window, xfFloatbar* floatbar)
{
int i, size;
size = ARRAYSIZE(floatbar->buttons);
if (!floatbar)
return;
if (window->floatbar == floatbar)
window->floatbar = NULL;
for (i = 0; i < size; i++)
{
xf_floatbar_button_free(xfc, floatbar->buttons[i]);
floatbar->buttons[i] = NULL;
}
if (floatbar->handle)
{
XUnmapWindow(xfc->display, floatbar->handle);
XDestroyWindow(xfc->display, floatbar->handle);
}
free(floatbar);
}

34
client/X11/xf_floatbar.h Normal file
View File

@ -0,0 +1,34 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* X11 Windows
*
* 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.
*/
#ifndef FREERDP_CLIENT_X11_FLOATBAR_H
#define FREERDP_CLIENT_X11_FLOATBAR_H
typedef struct xf_floatbar xfFloatbar;
#include "xfreerdp.h"
typedef void(*OnClick)(xfContext*);
xfFloatbar* xf_floatbar_new(xfContext* xfc, Window window);
BOOL xf_floatbar_event_process(xfContext* xfc, XEvent* event);
BOOL xf_floatbar_check_event(xfContext* xfc, XEvent* event);
void xf_floatbar_toggle_visibility(xfContext* xfc, bool visible);
void xf_floatbar_free(xfContext* xfc, xfWindow* window, xfFloatbar* floatbar);
void xf_floatbar_hide_and_show(xfContext* xfc);
void xf_floatbar_set_root_y(xfContext* xfc, int y);
#endif /* FREERDP_CLIENT_X11_FLOATBAR_H */

View File

@ -146,6 +146,11 @@ void xf_SendClientEvent(xfContext* xfc, Window window, Atom atom,
va_end(argp);
}
void xf_SetWindowMinimized(xfContext* xfc, xfWindow* window)
{
XIconifyWindow(xfc->display, window->handle, xfc->screen_number);
}
void xf_SetWindowFullscreen(xfContext* xfc, xfWindow* window, BOOL fullscreen)
{
int i;
@ -156,6 +161,9 @@ void xf_SetWindowFullscreen(xfContext* xfc, xfWindow* window, BOOL fullscreen)
window->decorations = xfc->decorations;
xf_SetWindowDecorations(xfc, window->handle, window->decorations);
if (xfc->floatbar)
xf_floatbar_toggle_visibility(xfc, fullscreen);
if (fullscreen)
{
xfc->savedWidth = xfc->window->width;
@ -569,6 +577,7 @@ xfWindow* xf_CreateDesktopWindow(xfContext* xfc, char* name, int width,
settings->DesktopPosY);
}
window->floatbar = xf_floatbar_new(xfc, window->handle);
xf_SetWindowTitleText(xfc, window->handle, name);
return window;
}
@ -619,6 +628,9 @@ void xf_DestroyDesktopWindow(xfContext* xfc, xfWindow* window)
if (xfc->window == window)
xfc->window = NULL;
if (window->floatbar)
xf_floatbar_free(xfc, window, window->floatbar);
if (window->gc)
XFreeGC(xfc->display, window->gc);

View File

@ -30,6 +30,7 @@ typedef struct xf_localmove xfLocalMove;
typedef struct xf_window xfWindow;
#include "xf_client.h"
#include "xf_floatbar.h"
#include "xfreerdp.h"
// Extended ICCM flags http://standards.freedesktop.org/wm-spec/wm-spec-latest.html
@ -80,6 +81,7 @@ struct xf_window
int shmid;
Window handle;
Window* xfwin;
xfFloatbar* floatbar;
BOOL decorations;
BOOL is_mapped;
BOOL is_transient;
@ -143,6 +145,7 @@ BOOL xf_GetCurrentDesktop(xfContext* xfc);
BOOL xf_GetWorkArea(xfContext* xfc);
void xf_SetWindowFullscreen(xfContext* xfc, xfWindow* window, BOOL fullscreen);
void xf_SetWindowMinimized(xfContext* xfc, xfWindow* window);
void xf_SetWindowDecorations(xfContext* xfc, Window window, BOOL show);
void xf_SetWindowUnlisted(xfContext* xfc, Window window);
@ -154,7 +157,7 @@ Window xf_CreateDummyWindow(xfContext* xfc);
void xf_DestroyDummyWindow(xfContext* xfc, Window window);
BOOL xf_GetWindowProperty(xfContext* xfc, Window window, Atom property, int length,
unsigned long* nitems, unsigned long* bytes, BYTE** prop);
unsigned long* nitems, unsigned long* bytes, BYTE** prop);
void xf_SendClientEvent(xfContext* xfc, Window window, Atom atom, unsigned int numArgs, ...);
int xf_AppWindowInit(xfContext* xfc, xfAppWindow* appWindow);
@ -163,13 +166,15 @@ void xf_MoveWindow(xfContext* xfc, xfAppWindow* appWindow, int x, int y, int wid
void xf_ShowWindow(xfContext* xfc, xfAppWindow* appWindow, BYTE state);
//void xf_SetWindowIcon(xfContext* xfc, xfAppWindow* appWindow, rdpIcon* icon);
void xf_SetWindowRects(xfContext* xfc, xfAppWindow* appWindow, RECTANGLE_16* rects, int nrects);
void xf_SetWindowVisibilityRects(xfContext* xfc, xfAppWindow* appWindow, UINT32 rectsOffsetX, UINT32 rectsOffsetY, RECTANGLE_16* rects, int nrects);
void xf_SetWindowVisibilityRects(xfContext* xfc, xfAppWindow* appWindow, UINT32 rectsOffsetX,
UINT32 rectsOffsetY, RECTANGLE_16* rects, int nrects);
void xf_SetWindowStyle(xfContext* xfc, xfAppWindow* appWindow, UINT32 style, UINT32 ex_style);
void xf_UpdateWindowArea(xfContext* xfc, xfAppWindow* appWindow, int x, int y, int width, int height);
void xf_UpdateWindowArea(xfContext* xfc, xfAppWindow* appWindow, int x, int y, int width,
int height);
void xf_DestroyWindow(xfContext* xfc, xfAppWindow* appWindow);
void xf_SetWindowMinMaxInfo(xfContext* xfc, xfAppWindow* appWindow,
int maxWidth, int maxHeight, int maxPosX, int maxPosY,
int minTrackWidth, int minTrackHeight, int maxTrackWidth, int maxTrackHeight);
int maxWidth, int maxHeight, int maxPosX, int maxPosY,
int minTrackWidth, int minTrackHeight, int maxTrackWidth, int maxTrackHeight);
void xf_StartLocalMoveSize(xfContext* xfc, xfAppWindow* appWindow, int direction, int x, int y);
void xf_EndLocalMoveSize(xfContext* xfc, xfAppWindow* appWindow);
xfAppWindow* xf_AppWindowFromX11Window(xfContext* xfc, Window wnd);

View File

@ -160,6 +160,7 @@ struct xf_context
BOOL use_xinput;
BOOL mouse_active;
BOOL fullscreen_toggle;
BOOL floatbar;
BOOL controlToggle;
UINT32 KeyboardLayout;
BOOL KeyboardState[256];

View File

@ -2460,6 +2460,10 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
{
settings->ToggleFullscreen = arg->Value ? TRUE : FALSE;
}
CommandLineSwitchCase(arg, "floatbar")
{
settings->Floatbar = arg->Value ? TRUE : FALSE;
}
CommandLineSwitchCase(arg, "mouse-motion")
{
settings->MouseMotion = arg->Value ? TRUE : FALSE;

View File

@ -69,6 +69,7 @@ static COMMAND_LINE_ARGUMENT_A args[] =
{ "f", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Fullscreen mode (<Ctrl>+<Alt>+<Enter> toggles fullscreen)" },
{ "fast-path", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "fast-path input/output" },
{ "fipsmode", COMMAND_LINE_VALUE_BOOL, NULL, NULL, NULL, -1, NULL, "FIPS mode" },
{ "floatbar", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "floatbar in fullscreen mode" },
{ "fonts", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "smooth fonts (ClearType)" },
{ "frame-ack", COMMAND_LINE_VALUE_REQUIRED, "<number>", NULL, NULL, -1, NULL, "Number of frame acknowledgement" },
{ "from-stdin", COMMAND_LINE_VALUE_OPTIONAL, "force", NULL, NULL, -1, NULL, "Read credentials from stdin. With <force> the prompt is done before connection, otherwise on server request." },

View File

@ -1486,6 +1486,7 @@ struct rdp_settings
ALIGN64 BYTE*
SettingsModified; /* byte array marking fields that have been modified from their default value */
ALIGN64 char* ActionScript;
ALIGN64 BOOL Floatbar;
};
typedef struct rdp_settings rdpSettings;

View File

@ -319,6 +319,7 @@ rdpSettings* freerdp_settings_new(DWORD flags)
settings->GatewayPort = 443;
settings->DesktopResize = TRUE;
settings->ToggleFullscreen = TRUE;
settings->Floatbar = TRUE;
settings->DesktopPosX = 0;
settings->DesktopPosY = 0;
settings->UnmapButtons = FALSE;