FreeRDP/client/X11/xf_event.c

935 lines
23 KiB
C
Raw Normal View History

2011-08-07 17:52:40 +04:00
/**
* FreeRDP: A Remote Desktop Protocol Client
* X11 Event Handling
*
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* 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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <freerdp/locale/keyboard.h>
2011-08-07 17:52:40 +04:00
#include "xf_rail.h"
#include "xf_window.h"
2011-09-23 07:37:17 +04:00
#include "xf_cliprdr.h"
2011-08-07 17:52:40 +04:00
#include "xf_event.h"
2012-03-23 00:30:15 +04:00
#ifdef WITH_DEBUG_X11
static const char* const X11_EVENT_STRINGS[] =
2011-08-19 19:12:30 +04:00
{
"", "",
"KeyPress",
"KeyRelease",
"ButtonPress",
"ButtonRelease",
"MotionNotify",
"EnterNotify",
"LeaveNotify",
"FocusIn",
"FocusOut",
"KeymapNotify",
"Expose",
"GraphicsExpose",
"NoExpose",
"VisibilityNotify",
"CreateNotify",
"DestroyNotify",
"UnmapNotify",
"MapNotify",
"MapRequest",
"ReparentNotify",
"ConfigureNotify",
"ConfigureRequest",
"GravityNotify",
"ResizeRequest",
"CirculateNotify",
"CirculateRequest",
"PropertyNotify",
"SelectionClear",
"SelectionRequest",
"SelectionNotify",
"ColormapNotify",
"ClientMessage",
"MappingNotify",
"GenericEvent",
};
2012-03-23 00:30:15 +04:00
#endif
2011-08-19 19:12:30 +04:00
static boolean xf_event_Expose(xfInfo* xfi, XEvent* event, boolean app)
{
int x, y;
int w, h;
x = event->xexpose.x;
y = event->xexpose.y;
w = event->xexpose.width;
h = event->xexpose.height;
if (app != true)
{
XCopyArea(xfi->display, xfi->primary, xfi->window->handle, xfi->gc, x, y, w, h, x, y);
}
else
{
xfWindow* xfw;
rdpWindow* window;
rdpRail* rail = ((rdpContext*) xfi->context)->rail;
window = window_list_get_by_extra_id(rail->list, (void*) event->xexpose.window);
if (window != NULL)
{
xfw = (xfWindow*) window->extra;
xf_UpdateWindowArea(xfi, xfw, x, y, w, h);
}
}
return true;
}
static boolean xf_event_VisibilityNotify(xfInfo* xfi, XEvent* event, boolean app)
{
2011-08-19 19:12:30 +04:00
xfi->unobscured = event->xvisibility.state == VisibilityUnobscured;
return true;
}
static boolean xf_event_MotionNotify(xfInfo* xfi, XEvent* event, boolean app)
{
rdpInput* input;
int x, y;
Window childWindow;
2011-08-07 17:52:40 +04:00
input = xfi->instance->input;
x = event->xmotion.x;
y = event->xmotion.y;
if (xfi->mouse_motion != true)
{
if ((event->xmotion.state & (Button1Mask | Button2Mask | Button3Mask)) == 0)
return true;
}
if (app)
{
// Translate to desktop coordinates
XTranslateCoordinates(xfi->display, event->xmotion.window,
RootWindowOfScreen(xfi->screen),
x, y, &x, &y, &childWindow);
}
input->MouseEvent(input, PTR_FLAGS_MOVE, x, y);
if (xfi->fullscreen)
{
XSetInputFocus(xfi->display, xfi->window->handle, RevertToPointerRoot, CurrentTime);
}
return true;
2011-08-07 17:52:40 +04:00
}
static boolean xf_event_ButtonPress(xfInfo* xfi, XEvent* event, boolean app)
2011-08-07 17:52:40 +04:00
{
int x, y;
int flags;
Window childWindow;
boolean wheel;
boolean extended;
rdpInput* input;
input = xfi->instance->input;
x = 0;
y = 0;
flags = 0;
wheel = false;
extended = false;
switch (event->xbutton.button)
{
case 1:
x = event->xbutton.x;
y = event->xbutton.y;
flags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1;
break;
case 2:
x = event->xbutton.x;
y = event->xbutton.y;
flags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON3;
break;
case 3:
x = event->xbutton.x;
y = event->xbutton.y;
flags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON2;
break;
case 4:
wheel = true;
flags = PTR_FLAGS_WHEEL | 0x0078;
break;
2011-08-07 17:52:40 +04:00
case 5:
wheel = true;
flags = PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x0088;
break;
case 6: // wheel left or back
case 8: // back
case 97: // Xming
extended = true;
x = event->xbutton.x;
y = event->xbutton.y;
flags = PTR_XFLAGS_DOWN | PTR_XFLAGS_BUTTON1;
break;
case 7: // wheel right or forward
case 9: // forward
case 112: // Xming
extended = true;
x = event->xbutton.x;
y = event->xbutton.y;
flags = PTR_XFLAGS_DOWN | PTR_XFLAGS_BUTTON2;
break;
default:
x = 0;
y = 0;
flags = 0;
break;
}
if (flags != 0)
{
if (wheel)
{
input->MouseEvent(input, flags, 0, 0);
}
else
{
if (app)
{
// Translate to desktop coordinates
XTranslateCoordinates(xfi->display, event->xmotion.window,
RootWindowOfScreen(xfi->screen),
x, y, &x, &y, &childWindow);
}
if (extended)
input->ExtendedMouseEvent(input, flags, x, y);
else
input->MouseEvent(input, flags, x, y);
}
}
return true;
2011-08-07 17:52:40 +04:00
}
static boolean xf_event_ButtonRelease(xfInfo* xfi, XEvent* event, boolean app)
2011-08-07 17:52:40 +04:00
{
int x, y;
int flags;
Window childWindow;
boolean extended;
rdpInput* input;
input = xfi->instance->input;
x = 0;
y = 0;
flags = 0;
extended = false;
switch (event->xbutton.button)
{
case 1:
x = event->xbutton.x;
y = event->xbutton.y;
flags = PTR_FLAGS_BUTTON1;
break;
case 2:
x = event->xbutton.x;
y = event->xbutton.y;
flags = PTR_FLAGS_BUTTON3;
break;
case 3:
x = event->xbutton.x;
y = event->xbutton.y;
flags = PTR_FLAGS_BUTTON2;
break;
case 6:
case 8:
case 97:
extended = true;
x = event->xbutton.x;
y = event->xbutton.y;
flags = PTR_XFLAGS_BUTTON1;
break;
case 7:
case 9:
case 112:
extended = true;
x = event->xbutton.x;
y = event->xbutton.y;
flags = PTR_XFLAGS_BUTTON2;
break;
default:
flags = 0;
break;
}
if (flags != 0)
{
if (app)
{
// Translate to desktop coordinates
XTranslateCoordinates(xfi->display, event->xmotion.window,
RootWindowOfScreen(xfi->screen),
x, y, &x, &y, &childWindow);
}
if (extended)
input->ExtendedMouseEvent(input, flags, x, y);
else
input->MouseEvent(input, flags, x, y);
}
return true;
}
static boolean xf_event_KeyPress(xfInfo* xfi, XEvent* event, boolean app)
{
KeySym keysym;
char str[256];
XLookupString((XKeyEvent*) event, str, sizeof(str), &keysym, NULL);
xf_kbd_set_keypress(xfi, event->xkey.keycode, keysym);
if (xfi->fullscreen_toggle && xf_kbd_handle_special_keys(xfi, keysym))
return true;
xf_kbd_send_key(xfi, true, event->xkey.keycode);
return true;
}
static boolean xf_event_KeyRelease(xfInfo* xfi, XEvent* event, boolean app)
{
XEvent next_event;
if (XPending(xfi->display))
{
memset(&next_event, 0, sizeof(next_event));
XPeekEvent(xfi->display, &next_event);
if (next_event.type == KeyPress)
{
if (next_event.xkey.keycode == event->xkey.keycode)
return true;
}
}
xf_kbd_unset_keypress(xfi, event->xkey.keycode);
xf_kbd_send_key(xfi, false, event->xkey.keycode);
return true;
}
2011-08-07 17:52:40 +04:00
static boolean xf_event_FocusIn(xfInfo* xfi, XEvent* event, boolean app)
{
if (event->xfocus.mode == NotifyGrab)
return true;
xfi->focused = true;
if (xfi->mouse_active && (app != true))
XGrabKeyboard(xfi->display, xfi->window->handle, true, GrabModeAsync, GrabModeAsync, CurrentTime);
if (app)
Multiple RAIL fixes/improvements 1. Linked Window Manager Maximize/Minimize and Restore operations to those from the Server Rail Window so that they are in sync 2. Enable things like "CTRL-ALT-DELETE" and "WindowsKey-L" to show the full desktop window again since the desktop is not actively monitored since this was still trying to draw to the rail window without updating the size of the window to accomodate the full workspace area. 3. Changed local window coordinates to be based on the visibileOffsetX/Y- while moving server window based on WindowOffsetX/Y. I have seen various issues regarding this when trying to use a maximized window where this is a disconnect between local window coordinates and remote window coordinates. This change clears these things up. 4. Commented the XShapeCombineRectangles calls - this can cause issues where the entire window is not visible and it does not currently play well with the changes from #3. The gain here is greater than the loss. 5. Draw the initial workspace correctly when running across multiple monitors. The correct size was always used, but the window was only starting on the current monitor and thus could draw the window off of the viewable area. Known Issues: Although the changes for #2 worked well in the stable branch that I developed from - the desktop window shown once the rail windows are destroyed does not respond to input unless I minimize/restore the window. Once the window starts responding to input - you can hit cancel to close the desktop window and return to your rail windows again(or launch task manager, etc.). This is still a big step in the right direction as xfreerdp is now correctly acting when the rail server stops Actively Monitoring the desktop. XShapeCombineRectangles needs to be revisited, most windows applications will give you a rectangular window anyways.
2012-08-04 02:35:17 +04:00
{
xf_rail_send_activate(xfi, event->xany.window, true);
rdpWindow* window;
rdpRail* rail = ((rdpContext*) xfi->context)->rail;
window = window_list_get_by_extra_id(rail->list, (void*) event->xany.window);
//Update the server with any window changes that occured while the window was not focused.
if (window != NULL)
xf_rail_adjust_position(xfi, window);
}
xf_kbd_focus_in(xfi);
if (app != true)
xf_cliprdr_check_owner(xfi);
2011-09-23 07:37:17 +04:00
return true;
}
static boolean xf_event_FocusOut(xfInfo* xfi, XEvent* event, boolean app)
{
if (event->xfocus.mode == NotifyUngrab)
return true;
xfi->focused = false;
if (event->xfocus.mode == NotifyWhileGrabbed)
XUngrabKeyboard(xfi->display, CurrentTime);
if (app)
xf_rail_send_activate(xfi, event->xany.window, false);
return true;
}
static boolean xf_event_MappingNotify(xfInfo* xfi, XEvent* event, boolean app)
{
if (event->xmapping.request == MappingModifier)
{
XFreeModifiermap(xfi->modifier_map);
xfi->modifier_map = XGetModifierMapping(xfi->display);
}
return true;
}
static boolean xf_event_ClientMessage(xfInfo* xfi, XEvent* event, boolean app)
{
if ((event->xclient.message_type == xfi->WM_PROTOCOLS)
&& ((Atom) event->xclient.data.l[0] == xfi->WM_DELETE_WINDOW))
{
if (app)
{
2012-03-23 00:30:15 +04:00
DEBUG_X11("RAIL window closed");
rdpWindow* window;
rdpRail* rail = ((rdpContext*) xfi->context)->rail;
window = window_list_get_by_extra_id(rail->list, (void*) event->xclient.window);
if (window != NULL)
{
xf_rail_send_client_system_command(xfi, window->windowId, SC_CLOSE);
}
return true;
}
else
{
2012-03-23 00:30:15 +04:00
DEBUG_X11("Main window closed");
return false;
}
}
return true;
2011-08-07 17:52:40 +04:00
}
static boolean xf_event_EnterNotify(xfInfo* xfi, XEvent* event, boolean app)
2011-08-07 17:52:40 +04:00
{
if (app != true)
{
xfi->mouse_active = true;
if (xfi->fullscreen)
XSetInputFocus(xfi->display, xfi->window->handle, RevertToPointerRoot, CurrentTime);
if (xfi->focused)
XGrabKeyboard(xfi->display, xfi->window->handle, true, GrabModeAsync, GrabModeAsync, CurrentTime);
}
else
{
/* keep track of which window has focus so that we can apply pointer updates */
xfWindow* xfw;
rdpWindow* window;
rdpRail* rail = ((rdpContext*) xfi->context)->rail;
window = window_list_get_by_extra_id(rail->list, (void*) event->xexpose.window);
if (window != NULL)
{
xfw = (xfWindow*) window->extra;
xfi->window = xfw;
}
}
return true;
2011-08-07 17:52:40 +04:00
}
static boolean xf_event_LeaveNotify(xfInfo* xfi, XEvent* event, boolean app)
{
if (app != true)
2011-08-19 19:12:30 +04:00
{
xfi->mouse_active = false;
2011-08-19 19:12:30 +04:00
XUngrabKeyboard(xfi->display, CurrentTime);
}
return true;
}
static boolean xf_event_ConfigureNotify(xfInfo* xfi, XEvent* event, boolean app)
{
rdpWindow* window;
rdpRail* rail = ((rdpContext*) xfi->context)->rail;
window = window_list_get_by_extra_id(rail->list, (void*) event->xconfigure.window);
if (window != NULL)
{
xfWindow* xfw;
Window childWindow;
xfw = (xfWindow*) window->extra;
/*
* ConfigureNotify coordinates are expressed relative to the window parent.
* Translate these to root window coordinates.
*/
XTranslateCoordinates(xfi->display, xfw->handle,
RootWindowOfScreen(xfi->screen),
0, 0, &xfw->left, &xfw->top, &childWindow);
xfw->width = event->xconfigure.width;
xfw->height = event->xconfigure.height;
xfw->right = xfw->left + xfw->width - 1;
xfw->bottom = xfw->top + xfw->height - 1;
DEBUG_X11_LMS("window=0x%X rc={l=%d t=%d r=%d b=%d} w=%u h=%u send_event=%d",
(uint32) xfw->handle, xfw->left, xfw->top, xfw->right, xfw->bottom,
xfw->width, xfw->height, event->xconfigure.send_event);
Multiple RAIL fixes/improvements 1. Linked Window Manager Maximize/Minimize and Restore operations to those from the Server Rail Window so that they are in sync 2. Enable things like "CTRL-ALT-DELETE" and "WindowsKey-L" to show the full desktop window again since the desktop is not actively monitored since this was still trying to draw to the rail window without updating the size of the window to accomodate the full workspace area. 3. Changed local window coordinates to be based on the visibileOffsetX/Y- while moving server window based on WindowOffsetX/Y. I have seen various issues regarding this when trying to use a maximized window where this is a disconnect between local window coordinates and remote window coordinates. This change clears these things up. 4. Commented the XShapeCombineRectangles calls - this can cause issues where the entire window is not visible and it does not currently play well with the changes from #3. The gain here is greater than the loss. 5. Draw the initial workspace correctly when running across multiple monitors. The correct size was always used, but the window was only starting on the current monitor and thus could draw the window off of the viewable area. Known Issues: Although the changes for #2 worked well in the stable branch that I developed from - the desktop window shown once the rail windows are destroyed does not respond to input unless I minimize/restore the window. Once the window starts responding to input - you can hit cancel to close the desktop window and return to your rail windows again(or launch task manager, etc.). This is still a big step in the right direction as xfreerdp is now correctly acting when the rail server stops Actively Monitoring the desktop. XShapeCombineRectangles needs to be revisited, most windows applications will give you a rectangular window anyways.
2012-08-04 02:35:17 +04:00
//additonal checks for not in a local move and not ignoring configure to send position update to server,
//also should the window not be focused then do not send to server yet(ie. resizing using window decoration).
//The server will be updated when the window gets refocused.
if (app && (!event->xconfigure.send_event || xfi->window->local_move.state == LMS_NOT_ACTIVE)
&& !xfw->rail_ignore_configure && xfi->focused)
xf_rail_adjust_position(xfi, window);
}
return True;
}
static boolean xf_event_MapNotify(xfInfo* xfi, XEvent* event, boolean app)
{
2012-05-28 16:21:56 +04:00
RECTANGLE_16 rect;
rdpWindow* window;
2012-05-28 16:21:56 +04:00
rdpUpdate* update = xfi->instance->update;
rdpRail* rail = ((rdpContext*) xfi->context)->rail;
if (app != true)
{
2012-05-28 16:21:56 +04:00
if (xfi->suppress_output == true)
{
xfi->suppress_output = false;
rect.left = 0;
rect.top = 0;
rect.right = xfi->width;
rect.bottom = xfi->height;
update->SuppressOutput((rdpContext*) xfi->context, 1, &rect);
}
}
else
{
window = window_list_get_by_extra_id(rail->list, (void*) event->xany.window);
if (window != NULL)
{
/* local restore event */
Multiple RAIL fixes/improvements 1. Linked Window Manager Maximize/Minimize and Restore operations to those from the Server Rail Window so that they are in sync 2. Enable things like "CTRL-ALT-DELETE" and "WindowsKey-L" to show the full desktop window again since the desktop is not actively monitored since this was still trying to draw to the rail window without updating the size of the window to accomodate the full workspace area. 3. Changed local window coordinates to be based on the visibileOffsetX/Y- while moving server window based on WindowOffsetX/Y. I have seen various issues regarding this when trying to use a maximized window where this is a disconnect between local window coordinates and remote window coordinates. This change clears these things up. 4. Commented the XShapeCombineRectangles calls - this can cause issues where the entire window is not visible and it does not currently play well with the changes from #3. The gain here is greater than the loss. 5. Draw the initial workspace correctly when running across multiple monitors. The correct size was always used, but the window was only starting on the current monitor and thus could draw the window off of the viewable area. Known Issues: Although the changes for #2 worked well in the stable branch that I developed from - the desktop window shown once the rail windows are destroyed does not respond to input unless I minimize/restore the window. Once the window starts responding to input - you can hit cancel to close the desktop window and return to your rail windows again(or launch task manager, etc.). This is still a big step in the right direction as xfreerdp is now correctly acting when the rail server stops Actively Monitoring the desktop. XShapeCombineRectangles needs to be revisited, most windows applications will give you a rectangular window anyways.
2012-08-04 02:35:17 +04:00
//This is now handled as part of the PropertyNotify
//Doing this here would inhibit the ability to restore a maximized window
//that is minimized back to the maximized state
//xf_rail_send_client_system_command(xfi, window->windowId, SC_RESTORE);
2012-05-28 16:21:56 +04:00
xfWindow *xfw = (xfWindow*) window->extra;
xfw->is_mapped = true;
}
}
return true;
}
static boolean xf_event_UnmapNotify(xfInfo* xfi, XEvent* event, boolean app)
{
rdpWindow* window;
2012-05-28 16:21:56 +04:00
rdpUpdate* update = xfi->instance->update;
rdpRail* rail = ((rdpContext*) xfi->context)->rail;
xf_kbd_release_all_keypress(xfi);
if (app != true)
{
2012-05-28 16:21:56 +04:00
if (xfi->suppress_output == false)
{
xfi->suppress_output = true;
update->SuppressOutput((rdpContext*) xfi->context, 0, NULL);
}
}
else
{
window = window_list_get_by_extra_id(rail->list, (void*) event->xany.window);
if (window != NULL)
{
xfWindow *xfw = (xfWindow*) window->extra;
xfw->is_mapped = false;
}
}
return true;
}
static boolean xf_event_SelectionNotify(xfInfo* xfi, XEvent* event, boolean app)
2011-09-23 07:37:17 +04:00
{
if (app != true)
{
if (xf_cliprdr_process_selection_notify(xfi, event))
return true;
}
2011-09-23 07:37:17 +04:00
return true;
2011-09-23 07:37:17 +04:00
}
static boolean xf_event_SelectionRequest(xfInfo* xfi, XEvent* event, boolean app)
2011-09-23 07:37:17 +04:00
{
if (app != true)
{
if (xf_cliprdr_process_selection_request(xfi, event))
return true;
}
2011-09-23 07:37:17 +04:00
return true;
2011-09-23 07:37:17 +04:00
}
static boolean xf_event_SelectionClear(xfInfo* xfi, XEvent* event, boolean app)
2011-09-23 07:37:17 +04:00
{
if (app != true)
{
if (xf_cliprdr_process_selection_clear(xfi, event))
return true;
}
2011-09-23 07:37:17 +04:00
return true;
2011-09-23 07:37:17 +04:00
}
static boolean xf_event_PropertyNotify(xfInfo* xfi, XEvent* event, boolean app)
2011-09-23 07:37:17 +04:00
{
Multiple RAIL fixes/improvements 1. Linked Window Manager Maximize/Minimize and Restore operations to those from the Server Rail Window so that they are in sync 2. Enable things like "CTRL-ALT-DELETE" and "WindowsKey-L" to show the full desktop window again since the desktop is not actively monitored since this was still trying to draw to the rail window without updating the size of the window to accomodate the full workspace area. 3. Changed local window coordinates to be based on the visibileOffsetX/Y- while moving server window based on WindowOffsetX/Y. I have seen various issues regarding this when trying to use a maximized window where this is a disconnect between local window coordinates and remote window coordinates. This change clears these things up. 4. Commented the XShapeCombineRectangles calls - this can cause issues where the entire window is not visible and it does not currently play well with the changes from #3. The gain here is greater than the loss. 5. Draw the initial workspace correctly when running across multiple monitors. The correct size was always used, but the window was only starting on the current monitor and thus could draw the window off of the viewable area. Known Issues: Although the changes for #2 worked well in the stable branch that I developed from - the desktop window shown once the rail windows are destroyed does not respond to input unless I minimize/restore the window. Once the window starts responding to input - you can hit cancel to close the desktop window and return to your rail windows again(or launch task manager, etc.). This is still a big step in the right direction as xfreerdp is now correctly acting when the rail server stops Actively Monitoring the desktop. XShapeCombineRectangles needs to be revisited, most windows applications will give you a rectangular window anyways.
2012-08-04 02:35:17 +04:00
//This section handles sending the appropriate commands to the rail server
//when the window has been minimized, maximized, restored locally
//ie. not using the buttons on the rail window itself
if (app == true)
{
rdpWindow* window;
rdpRail* rail = ((rdpContext*) xfi->context)->rail;
window = window_list_get_by_extra_id(rail->list, (void*) event->xany.window);
if ((((Atom)event->xproperty.atom == xfi->_NET_WM_STATE) && (event->xproperty.state != PropertyDelete)) ||
(((Atom)event->xproperty.atom == xfi->WM_STATE) && (event->xproperty.state != PropertyDelete)))
{
boolean status;
boolean maxVert = false;
boolean maxHorz = false;
boolean minimized = false;
unsigned long nitems;
unsigned long bytes;
unsigned char* prop;
int i;
status = xf_GetWindowProperty(xfi, event->xproperty.window,
xfi->_NET_WM_STATE, 12, &nitems, &bytes, &prop);
if (status != true) {
DEBUG_X11_LMS("No return _NET_WM_STATE, window is not maximized");
}
for (i=0;i<nitems;i++)
{
if ((Atom) ((uint16 **) prop)[i] == XInternAtom(xfi->display, "_NET_WM_STATE_MAXIMIZED_VERT", False))
{
maxVert = true;
}
if ((Atom) ((uint16 **)prop)[i] == XInternAtom(xfi->display, "_NET_WM_STATE_MAXIMIZED_HORZ", False))
{
maxHorz = true;
}
}
XFree(prop);
status = xf_GetWindowProperty(xfi, event->xproperty.window,
xfi->WM_STATE, 1, &nitems, &bytes, &prop);
if (status != true) {
DEBUG_X11_LMS("No return WM_STATE, window is not minimized");
}
else
{
//If the window is in the iconic state
if (((uint32) *prop == 3))
{
minimized = true;
}
else
minimized = false;
XFree(prop);
}
if (maxVert && maxHorz && !minimized && (xfi->window->rail_state != WINDOW_SHOW_MAXIMIZED))
{
DEBUG_X11_LMS("Send SC_MAXIMIZE command to rail server.");
xfi->window->rail_state = WINDOW_SHOW_MAXIMIZED;
xf_rail_send_client_system_command(xfi, window->windowId, SC_MAXIMIZE);
}
else if (minimized && (xfi->window->rail_state != WINDOW_SHOW_MINIMIZED))
{
DEBUG_X11_LMS("Send SC_MINIMIZE command to rail server.");
xfi->window->rail_state = WINDOW_SHOW_MINIMIZED;
xf_rail_send_client_system_command(xfi, window->windowId, SC_MINIMIZE);
}
else if (!minimized && !maxVert && !maxHorz && (xfi->window->rail_state != WINDOW_SHOW))
{
DEBUG_X11_LMS("Send SC_RESTORE command to rail server");
xfi->window->rail_state = WINDOW_SHOW;
xf_rail_send_client_system_command(xfi, window->windowId, SC_RESTORE);
}
}
}
if (app != true)
{
if (xf_cliprdr_process_property_notify(xfi, event))
return true;
}
2011-09-23 07:37:17 +04:00
return true;
2011-09-23 07:37:17 +04:00
}
static boolean xf_event_suppress_events(xfInfo *xfi, rdpWindow *window, XEvent*event)
{
if (! xfi->remote_app)
return false;
switch (xfi->window->local_move.state)
{
case LMS_NOT_ACTIVE:
// No local move in progress, nothing to do
Multiple RAIL fixes/improvements 1. Linked Window Manager Maximize/Minimize and Restore operations to those from the Server Rail Window so that they are in sync 2. Enable things like "CTRL-ALT-DELETE" and "WindowsKey-L" to show the full desktop window again since the desktop is not actively monitored since this was still trying to draw to the rail window without updating the size of the window to accomodate the full workspace area. 3. Changed local window coordinates to be based on the visibileOffsetX/Y- while moving server window based on WindowOffsetX/Y. I have seen various issues regarding this when trying to use a maximized window where this is a disconnect between local window coordinates and remote window coordinates. This change clears these things up. 4. Commented the XShapeCombineRectangles calls - this can cause issues where the entire window is not visible and it does not currently play well with the changes from #3. The gain here is greater than the loss. 5. Draw the initial workspace correctly when running across multiple monitors. The correct size was always used, but the window was only starting on the current monitor and thus could draw the window off of the viewable area. Known Issues: Although the changes for #2 worked well in the stable branch that I developed from - the desktop window shown once the rail windows are destroyed does not respond to input unless I minimize/restore the window. Once the window starts responding to input - you can hit cancel to close the desktop window and return to your rail windows again(or launch task manager, etc.). This is still a big step in the right direction as xfreerdp is now correctly acting when the rail server stops Actively Monitoring the desktop. XShapeCombineRectangles needs to be revisited, most windows applications will give you a rectangular window anyways.
2012-08-04 02:35:17 +04:00
//Prevent Configure from happening during indeterminant state of Horz or Vert Max only
if ( (event->type == ConfigureNotify) && xfi->window->rail_ignore_configure)
{
DEBUG_X11_LMS("ConfigureNotify Event Ignored");
xfi->window->rail_ignore_configure = false;
return true;
}
break;
case LMS_STARTING:
// Local move initiated by RDP server, but we
// have not yet seen any updates from the X server
switch(event->type)
{
case ConfigureNotify:
// Starting to see move events
// from the X server. Local
// move is now in progress.
xfi->window->local_move.state = LMS_ACTIVE;
// Allow these events to be processed during move to keep
// our state up to date.
break;
case ButtonPress:
case ButtonRelease:
case KeyPress:
case KeyRelease:
case UnmapNotify:
// A button release event means the X
// window server did not grab the
// mouse before the user released it.
// In this case we must cancel the
// local move. The event will be
// processed below as normal, below.
break;
case VisibilityNotify:
case PropertyNotify:
case Expose:
// Allow these events to pass
break;
default:
// Eat any other events
return true;
}
break;
case LMS_ACTIVE:
// Local move is in progress
switch(event->type)
{
case ConfigureNotify:
case VisibilityNotify:
case PropertyNotify:
case Expose:
Multiple RAIL fixes/improvements 1. Linked Window Manager Maximize/Minimize and Restore operations to those from the Server Rail Window so that they are in sync 2. Enable things like "CTRL-ALT-DELETE" and "WindowsKey-L" to show the full desktop window again since the desktop is not actively monitored since this was still trying to draw to the rail window without updating the size of the window to accomodate the full workspace area. 3. Changed local window coordinates to be based on the visibileOffsetX/Y- while moving server window based on WindowOffsetX/Y. I have seen various issues regarding this when trying to use a maximized window where this is a disconnect between local window coordinates and remote window coordinates. This change clears these things up. 4. Commented the XShapeCombineRectangles calls - this can cause issues where the entire window is not visible and it does not currently play well with the changes from #3. The gain here is greater than the loss. 5. Draw the initial workspace correctly when running across multiple monitors. The correct size was always used, but the window was only starting on the current monitor and thus could draw the window off of the viewable area. Known Issues: Although the changes for #2 worked well in the stable branch that I developed from - the desktop window shown once the rail windows are destroyed does not respond to input unless I minimize/restore the window. Once the window starts responding to input - you can hit cancel to close the desktop window and return to your rail windows again(or launch task manager, etc.). This is still a big step in the right direction as xfreerdp is now correctly acting when the rail server stops Actively Monitoring the desktop. XShapeCombineRectangles needs to be revisited, most windows applications will give you a rectangular window anyways.
2012-08-04 02:35:17 +04:00
case GravityNotify:
// Keep us up to date on position
break;
default:
Multiple RAIL fixes/improvements 1. Linked Window Manager Maximize/Minimize and Restore operations to those from the Server Rail Window so that they are in sync 2. Enable things like "CTRL-ALT-DELETE" and "WindowsKey-L" to show the full desktop window again since the desktop is not actively monitored since this was still trying to draw to the rail window without updating the size of the window to accomodate the full workspace area. 3. Changed local window coordinates to be based on the visibileOffsetX/Y- while moving server window based on WindowOffsetX/Y. I have seen various issues regarding this when trying to use a maximized window where this is a disconnect between local window coordinates and remote window coordinates. This change clears these things up. 4. Commented the XShapeCombineRectangles calls - this can cause issues where the entire window is not visible and it does not currently play well with the changes from #3. The gain here is greater than the loss. 5. Draw the initial workspace correctly when running across multiple monitors. The correct size was always used, but the window was only starting on the current monitor and thus could draw the window off of the viewable area. Known Issues: Although the changes for #2 worked well in the stable branch that I developed from - the desktop window shown once the rail windows are destroyed does not respond to input unless I minimize/restore the window. Once the window starts responding to input - you can hit cancel to close the desktop window and return to your rail windows again(or launch task manager, etc.). This is still a big step in the right direction as xfreerdp is now correctly acting when the rail server stops Actively Monitoring the desktop. XShapeCombineRectangles needs to be revisited, most windows applications will give you a rectangular window anyways.
2012-08-04 02:35:17 +04:00
DEBUG_X11_LMS("Event Type to break LMS: %s", X11_EVENT_STRINGS[event->type]);
// Any other event terminates move
xf_rail_end_local_move(xfi, window);
break;
}
break;
case LMS_TERMINATING:
// Already sent RDP end move to sever
// Allow events to pass.
break;
}
return false;
}
boolean xf_event_process(freerdp* instance, XEvent* event)
{
boolean status = true;
xfInfo* xfi = ((xfContext*) instance->context)->xfi;
rdpRail* rail = ((rdpContext*) xfi->context)->rail;
rdpWindow* window;
if (xfi->remote_app)
{
window = window_list_get_by_extra_id(
rail->list, (void*) event->xexpose.window);
if (window)
{
// Update "current" window for cursor change orders
xfi->window = (xfWindow *) window->extra;
if (xf_event_suppress_events(xfi, window, event))
return true;
}
}
2011-08-19 19:12:30 +04:00
if (event->type != MotionNotify)
2012-03-23 00:30:15 +04:00
DEBUG_X11("%s Event(%d): wnd=0x%04X", X11_EVENT_STRINGS[event->type], event->type, (uint32) event->xany.window);
2011-08-19 19:12:30 +04:00
switch (event->type)
{
case Expose:
status = xf_event_Expose(xfi, event, xfi->remote_app);
break;
case VisibilityNotify:
status = xf_event_VisibilityNotify(xfi, event, xfi->remote_app);
break;
case MotionNotify:
status = xf_event_MotionNotify(xfi, event, xfi->remote_app);
break;
case ButtonPress:
status = xf_event_ButtonPress(xfi, event, xfi->remote_app);
break;
case ButtonRelease:
status = xf_event_ButtonRelease(xfi, event, xfi->remote_app);
break;
case KeyPress:
status = xf_event_KeyPress(xfi, event, xfi->remote_app);
break;
case KeyRelease:
status = xf_event_KeyRelease(xfi, event, xfi->remote_app);
break;
case FocusIn:
status = xf_event_FocusIn(xfi, event, xfi->remote_app);
break;
case FocusOut:
status = xf_event_FocusOut(xfi, event, xfi->remote_app);
break;
case EnterNotify:
status = xf_event_EnterNotify(xfi, event, xfi->remote_app);
break;
case LeaveNotify:
status = xf_event_LeaveNotify(xfi, event, xfi->remote_app);
break;
case NoExpose:
break;
case GraphicsExpose:
break;
case ConfigureNotify:
status = xf_event_ConfigureNotify(xfi, event, xfi->remote_app);
break;
case MapNotify:
status = xf_event_MapNotify(xfi, event, xfi->remote_app);
break;
case UnmapNotify:
status = xf_event_UnmapNotify(xfi, event, xfi->remote_app);
break;
case ReparentNotify:
break;
case MappingNotify:
status = xf_event_MappingNotify(xfi, event, xfi->remote_app);
break;
case ClientMessage:
status = xf_event_ClientMessage(xfi, event, xfi->remote_app);
break;
2011-09-23 07:37:17 +04:00
case SelectionNotify:
status = xf_event_SelectionNotify(xfi, event, xfi->remote_app);
2011-09-23 07:37:17 +04:00
break;
case SelectionRequest:
status = xf_event_SelectionRequest(xfi, event, xfi->remote_app);
2011-09-23 07:37:17 +04:00
break;
case SelectionClear:
status = xf_event_SelectionClear(xfi, event, xfi->remote_app);
2011-09-23 07:37:17 +04:00
break;
case PropertyNotify:
status = xf_event_PropertyNotify(xfi, event, xfi->remote_app);
2011-09-23 07:37:17 +04:00
break;
}
return status;
}