931 lines
24 KiB
Objective-C
931 lines
24 KiB
Objective-C
/**
|
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
|
* MacFreeRDP
|
|
*
|
|
* Copyright 2012 Thomas Goddard
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
#include "MRDPRailView.h"
|
|
|
|
#define USE_RAIL_CVT
|
|
|
|
@implementation MRDPRailView
|
|
|
|
@synthesize mrdpRailWindow, windowIndex, activateWindow;
|
|
|
|
MRDPRailView* g_mrdpRailView;
|
|
|
|
- (void) updateDisplay
|
|
{
|
|
BOOL moveWindow = NO;
|
|
NSRect srcRectOuter;
|
|
NSRect destRectOuter;
|
|
|
|
rdpGdi* gdi;
|
|
|
|
if ((context == 0) || (context->gdi == 0))
|
|
return;
|
|
|
|
if (context->gdi->primary->hdc->hwnd->invalid->null)
|
|
return;
|
|
|
|
if (context->gdi->drawing != context->gdi->primary)
|
|
return;
|
|
|
|
gdi = context->gdi;
|
|
|
|
srcRectOuter = NSMakeRect(0, 0, self->width, self->height);
|
|
destRectOuter = [[self window] frame];
|
|
|
|
// cannot be bigger than our current screen size
|
|
NSRect screenSize = [[NSScreen mainScreen] frame];
|
|
|
|
if (destRectOuter.size.width > screenSize.size.width)
|
|
{
|
|
destRectOuter.size.width = screenSize.size.width;
|
|
moveWindow = YES;
|
|
}
|
|
|
|
if (destRectOuter.size.height > screenSize.size.height)
|
|
{
|
|
destRectOuter.size.height = screenSize.size.height;
|
|
moveWindow = YES;
|
|
}
|
|
|
|
if (destRectOuter.origin.x + destRectOuter.size.width > width)
|
|
destRectOuter.size.width = width - destRectOuter.origin.x;
|
|
|
|
[self setupBmiRep:destRectOuter.size.width :destRectOuter.size.height];
|
|
|
|
if (moveWindow)
|
|
{
|
|
moveWindow = NO;
|
|
RAIL_WINDOW_MOVE_ORDER newWndLoc;
|
|
apple_to_windowMove(&destRectOuter, &newWndLoc);
|
|
newWndLoc.windowId = savedWindowId;
|
|
//skipMoveWindowOnce = TRUE;
|
|
//mac_send_rail_client_event(g_mrdpRailView->rdp_instance->context->channels, RDP_EVENT_TYPE_RAIL_CLIENT_WINDOW_MOVE, &newWndLoc);
|
|
}
|
|
|
|
destRectOuter.origin.y = height - destRectOuter.origin.y - destRectOuter.size.height;
|
|
rail_convert_color_space(pixelData, (char *) gdi->primary_buffer,
|
|
&destRectOuter, self->width, self->height);
|
|
|
|
if (moveWindow)
|
|
[self setNeedsDisplayInRect:destRectOuter];
|
|
else
|
|
[self setNeedsDisplayInRect:[self frame]];
|
|
|
|
gdi->primary->hdc->hwnd->ninvalid = 0;
|
|
}
|
|
|
|
/** *********************************************************************
|
|
* called when our view needs to be redrawn
|
|
***********************************************************************/
|
|
|
|
- (void) drawRect:(NSRect)dirtyRect
|
|
{
|
|
[bmiRep drawInRect:dirtyRect fromRect:dirtyRect operation:NSCompositeCopy fraction:1.0 respectFlipped:NO hints:nil];
|
|
|
|
if (pixelData)
|
|
{
|
|
free(pixelData);
|
|
pixelData = NULL;
|
|
}
|
|
|
|
bmiRep = nil;
|
|
}
|
|
|
|
/** *********************************************************************
|
|
* become first responder so we can get keyboard and mouse events
|
|
***********************************************************************/
|
|
|
|
- (BOOL)acceptsFirstResponder
|
|
{
|
|
return YES;
|
|
}
|
|
|
|
- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
|
|
{
|
|
return NO;
|
|
}
|
|
|
|
/** *********************************************************************
|
|
* called when a mouse move event occurs
|
|
*
|
|
* ideally we want to be called when the mouse moves over NSView client area,
|
|
* but in reality we get called any time the mouse moves anywhere on the screen;
|
|
* we could use NSTrackingArea class to handle this but this class is available
|
|
* on Mac OS X v10.5 and higher; since we want to be compatible with older
|
|
* versions, we do this manually.
|
|
*
|
|
* TODO: here is how it can be done using legacy methods
|
|
* http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/EventOverview/MouseTrackingEvents/MouseTrackingEvents.html#//apple_ref/doc/uid/10000060i-CH11-SW1
|
|
***********************************************************************/
|
|
|
|
- (void) mouseMoved:(NSEvent *)event
|
|
{
|
|
[super mouseMoved:event];
|
|
|
|
NSRect winFrame = [[self window] frame];
|
|
NSPoint loc = [event locationInWindow];
|
|
|
|
int x = (int) (winFrame.origin.x + loc.x);
|
|
int y = (int) (winFrame.origin.y + loc.y);
|
|
|
|
y = height - y;
|
|
|
|
/* send mouse motion event to RDP server */
|
|
rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_MOVE, x, y);
|
|
}
|
|
|
|
/** *********************************************************************
|
|
* called when left mouse button is pressed down
|
|
***********************************************************************/
|
|
|
|
- (void)mouseDown:(NSEvent *) event
|
|
{
|
|
[super mouseDown:event];
|
|
|
|
NSRect winFrame = [[self window] frame];
|
|
NSPoint loc = [event locationInWindow];
|
|
int x = (int) (winFrame.origin.x + loc.x);
|
|
int y = (int) (winFrame.origin.y + loc.y);
|
|
int yPos = (int) (winFrame.size.height - loc.y);
|
|
|
|
y = height - y;
|
|
|
|
if ((yPos >= 4) && (yPos <= 20))
|
|
titleBarClicked = YES;
|
|
else
|
|
titleBarClicked = NO;
|
|
|
|
savedDragLocation.x = loc.x;
|
|
savedDragLocation.y = loc.y;
|
|
|
|
rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1, x, y);
|
|
}
|
|
|
|
/** *********************************************************************
|
|
* called when left mouse button is released
|
|
***********************************************************************/
|
|
|
|
- (void) mouseUp:(NSEvent *) event
|
|
{
|
|
[super mouseUp:event];
|
|
|
|
NSRect winFrame = [[self window] frame];
|
|
NSPoint loc = [event locationInWindow];
|
|
int x = (int) (winFrame.origin.x + loc.x);
|
|
int y = (int) (winFrame.origin.y + loc.y);
|
|
y = height - y;
|
|
|
|
rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_BUTTON1, x, y);
|
|
titleBarClicked = NO;
|
|
}
|
|
|
|
/** *********************************************************************
|
|
* called when right mouse button is pressed down
|
|
***********************************************************************/
|
|
|
|
- (void) rightMouseDown:(NSEvent *)event
|
|
{
|
|
[super rightMouseDown:event];
|
|
|
|
NSRect winFrame = [[self window] frame];
|
|
NSPoint loc = [event locationInWindow];
|
|
int x = (int) (winFrame.origin.x + loc.x);
|
|
int y = (int) (winFrame.origin.y + loc.y);
|
|
y = height - y;
|
|
|
|
rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON2, x, y);
|
|
}
|
|
|
|
/** *********************************************************************
|
|
* called when right mouse button is released
|
|
***********************************************************************/
|
|
|
|
- (void) rightMouseUp:(NSEvent *)event
|
|
{
|
|
[super rightMouseUp:event];
|
|
|
|
NSRect winFrame = [[self window] frame];
|
|
NSPoint loc = [event locationInWindow];
|
|
int x = (int) (winFrame.origin.x + loc.x);
|
|
int y = (int) (winFrame.origin.y + loc.y);
|
|
y = height - y;
|
|
|
|
rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_BUTTON2, x, y);
|
|
}
|
|
|
|
/** *********************************************************************
|
|
* called when middle mouse button is pressed
|
|
***********************************************************************/
|
|
|
|
- (void) otherMouseDown:(NSEvent *)event
|
|
{
|
|
[super otherMouseDown:event];
|
|
|
|
NSRect winFrame = [[self window] frame];
|
|
NSPoint loc = [event locationInWindow];
|
|
int x = (int) (winFrame.origin.x + loc.x);
|
|
int y = (int) (winFrame.origin.y + loc.y);
|
|
y = height - y;
|
|
|
|
rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON3, x, y);
|
|
}
|
|
|
|
/** *********************************************************************
|
|
* called when middle mouse button is released
|
|
***********************************************************************/
|
|
|
|
- (void) otherMouseUp:(NSEvent *)event
|
|
{
|
|
[super otherMouseUp:event];
|
|
|
|
NSRect winFrame = [[self window] frame];
|
|
NSPoint loc = [event locationInWindow];
|
|
int x = (int) (winFrame.origin.x + loc.x);
|
|
int y = (int) (winFrame.origin.y + loc.y);
|
|
y = height - y;
|
|
|
|
rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_BUTTON3, x, y);
|
|
}
|
|
|
|
- (void) scrollWheel:(NSEvent *)event
|
|
{
|
|
uint16 flags;
|
|
|
|
[super scrollWheel:event];
|
|
|
|
// we get more two finger trackpad scroll events
|
|
// than scrollWheel events, so we drop some
|
|
|
|
if (gestureEventInProgress)
|
|
{
|
|
scrollWheelCount++;
|
|
|
|
if (scrollWheelCount % 8 != 0)
|
|
return;
|
|
}
|
|
|
|
if ([event scrollingDeltaY] < 0)
|
|
{
|
|
flags = PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x0088;
|
|
}
|
|
else
|
|
{
|
|
flags = PTR_FLAGS_WHEEL | 0x78;
|
|
}
|
|
|
|
rdp_instance->input->MouseEvent(rdp_instance->input, flags, 0, 0);
|
|
}
|
|
|
|
/** *********************************************************************
|
|
* called when mouse is moved with left button pressed
|
|
* note: invocation order is: mouseDown, mouseDragged, mouseUp
|
|
***********************************************************************/
|
|
- (void) mouseDragged:(NSEvent *)event
|
|
{
|
|
[super mouseDragged:event];
|
|
|
|
NSRect winFrame = [[self window] frame];
|
|
NSPoint loc = [event locationInWindow];
|
|
int x = (int) loc.x;
|
|
int y = (int) loc.y;
|
|
|
|
if (titleBarClicked)
|
|
{
|
|
// window is being dragged to a new location
|
|
int newX = x - savedDragLocation.x;
|
|
int newY = y - savedDragLocation.y;
|
|
|
|
if ((newX == 0) && (newY == 0))
|
|
return;
|
|
|
|
winFrame.origin.x += newX;
|
|
winFrame.origin.y += newY;
|
|
|
|
[[self window] setFrame:winFrame display:YES];
|
|
return;
|
|
}
|
|
|
|
if (localMoveType == RAIL_WMSZ_LEFT)
|
|
{
|
|
// left border resize taking place
|
|
int diff = (int) (loc.x - savedDragLocation.x);
|
|
|
|
if (diff == 0)
|
|
return;
|
|
|
|
if (diff < 0)
|
|
{
|
|
diff = abs(diff);
|
|
winFrame.origin.x -= diff;
|
|
winFrame.size.width += diff;
|
|
}
|
|
else
|
|
{
|
|
winFrame.origin.x += diff;
|
|
winFrame.size.width -= diff;
|
|
}
|
|
|
|
[[self window] setFrame:winFrame display:YES];
|
|
return;
|
|
}
|
|
|
|
if (localMoveType == RAIL_WMSZ_RIGHT)
|
|
{
|
|
// right border resize taking place
|
|
int diff = (int) (loc.x - savedDragLocation.x);
|
|
|
|
if (diff == 0)
|
|
return;
|
|
|
|
savedDragLocation.x = loc.x;
|
|
savedDragLocation.y = loc.y;
|
|
|
|
winFrame.size.width += diff;
|
|
[[self window] setFrame:winFrame display:YES];
|
|
|
|
return;
|
|
}
|
|
|
|
if (localMoveType == RAIL_WMSZ_TOP)
|
|
{
|
|
// top border resize taking place
|
|
int diff = (int) (loc.y - savedDragLocation.y);
|
|
|
|
if (diff == 0)
|
|
return;
|
|
|
|
savedDragLocation.x = loc.x;
|
|
savedDragLocation.y = loc.y;
|
|
|
|
winFrame.size.height += diff;
|
|
[[self window] setFrame:winFrame display:YES];
|
|
|
|
return;
|
|
}
|
|
|
|
if (localMoveType == RAIL_WMSZ_BOTTOM)
|
|
{
|
|
// bottom border resize taking place
|
|
int diff = (int) (loc.y - savedDragLocation.y);
|
|
|
|
if (diff == 0)
|
|
return;
|
|
|
|
if (diff < 0)
|
|
{
|
|
diff = abs(diff);
|
|
winFrame.origin.y -= diff;
|
|
winFrame.size.height += diff;
|
|
}
|
|
else
|
|
{
|
|
winFrame.origin.y += diff;
|
|
winFrame.size.height -= diff;
|
|
}
|
|
|
|
[[self window] setFrame:winFrame display:YES];
|
|
return;
|
|
}
|
|
|
|
if (localMoveType == RAIL_WMSZ_TOPLEFT)
|
|
{
|
|
// top left border resize taking place
|
|
int diff = (int) (loc.x - savedDragLocation.x);
|
|
|
|
if (diff != 0)
|
|
{
|
|
if (diff < 0)
|
|
{
|
|
diff = abs(diff);
|
|
winFrame.origin.x -= diff;
|
|
winFrame.size.width += diff;
|
|
}
|
|
else
|
|
{
|
|
winFrame.origin.x += diff;
|
|
winFrame.size.width -= diff;
|
|
}
|
|
}
|
|
|
|
diff = (int) (loc.y - savedDragLocation.y);
|
|
|
|
if (diff != 0)
|
|
{
|
|
savedDragLocation.y = loc.y;
|
|
winFrame.size.height += diff;
|
|
}
|
|
|
|
[[self window] setFrame:winFrame display:YES];
|
|
return;
|
|
}
|
|
|
|
if (localMoveType == RAIL_WMSZ_TOPRIGHT)
|
|
{
|
|
// top right border resize taking place
|
|
int diff = (int) (loc.x - savedDragLocation.x);
|
|
|
|
if (diff != 0)
|
|
winFrame.size.width += diff;
|
|
|
|
diff = (int) (loc.y - savedDragLocation.y);
|
|
|
|
if (diff != 0)
|
|
winFrame.size.height += diff;
|
|
|
|
savedDragLocation.x = loc.x;
|
|
savedDragLocation.y = loc.y;
|
|
|
|
[[self window] setFrame:winFrame display:YES];
|
|
return;
|
|
}
|
|
|
|
if (localMoveType == RAIL_WMSZ_BOTTOMLEFT)
|
|
{
|
|
// bottom left border resize taking place
|
|
int diff = (int) (loc.x - savedDragLocation.x);
|
|
|
|
if (diff != 0)
|
|
{
|
|
if (diff < 0)
|
|
{
|
|
diff = abs(diff);
|
|
winFrame.origin.x -= diff;
|
|
winFrame.size.width += diff;
|
|
}
|
|
else
|
|
{
|
|
winFrame.origin.x += diff;
|
|
winFrame.size.width -= diff;
|
|
}
|
|
}
|
|
|
|
diff = (int) (loc.y - savedDragLocation.y);
|
|
|
|
if (diff != 0)
|
|
{
|
|
if (diff < 0)
|
|
{
|
|
diff = abs(diff);
|
|
winFrame.origin.y -= diff;
|
|
winFrame.size.height += diff;
|
|
}
|
|
else
|
|
{
|
|
winFrame.origin.y += diff;
|
|
winFrame.size.height -= diff;
|
|
}
|
|
}
|
|
|
|
[[self window] setFrame:winFrame display:YES];
|
|
return;
|
|
}
|
|
|
|
if (localMoveType == RAIL_WMSZ_BOTTOMRIGHT)
|
|
{
|
|
// bottom right border resize taking place
|
|
int diff = (int) (loc.x - savedDragLocation.x);
|
|
|
|
if (diff != 0)
|
|
{
|
|
savedDragLocation.x = loc.x;
|
|
//savedDragLocation.y = loc.y;
|
|
winFrame.size.width += diff;
|
|
}
|
|
|
|
diff = (int) (loc.y - savedDragLocation.y);
|
|
|
|
if (diff != 0)
|
|
{
|
|
if (diff < 0)
|
|
{
|
|
diff = abs(diff);
|
|
winFrame.origin.y -= diff;
|
|
winFrame.size.height += diff;
|
|
}
|
|
else
|
|
{
|
|
winFrame.origin.y += diff;
|
|
winFrame.size.height -= diff;
|
|
}
|
|
}
|
|
|
|
[[self window] setFrame:winFrame display:YES];
|
|
return;
|
|
}
|
|
|
|
x = (int) (winFrame.origin.x + loc.x);
|
|
y = (int) (winFrame.origin.y + loc.y);
|
|
y = height - y;
|
|
|
|
// send mouse motion event to RDP server
|
|
rdp_instance->input->MouseEvent(rdp_instance->input, PTR_FLAGS_MOVE, x, y);
|
|
}
|
|
|
|
/** *********************************************************************
|
|
* called when a key is pressed
|
|
***********************************************************************/
|
|
|
|
- (void) keyDown:(NSEvent *) event
|
|
{
|
|
int key;
|
|
USHORT extended;
|
|
DWORD vkcode;
|
|
DWORD scancode;
|
|
|
|
key = [event keyCode] + 8;
|
|
|
|
vkcode = GetVirtualKeyCodeFromKeycode(key, KEYCODE_TYPE_APPLE);
|
|
scancode = GetVirtualScanCodeFromVirtualKeyCode(vkcode, 4);
|
|
extended = (scancode & KBDEXT) ? KBDEXT : 0;
|
|
|
|
rdp_instance->input->KeyboardEvent(rdp_instance->input, extended | KBD_FLAGS_DOWN, scancode & 0xFF);
|
|
}
|
|
|
|
/** *********************************************************************
|
|
* called when a key is released
|
|
***********************************************************************/
|
|
|
|
- (void) keyUp:(NSEvent *) event
|
|
{
|
|
int key;
|
|
USHORT extended;
|
|
DWORD vkcode;
|
|
DWORD scancode;
|
|
|
|
key = [event keyCode] + 8;
|
|
|
|
vkcode = GetVirtualKeyCodeFromKeycode(key, KEYCODE_TYPE_APPLE);
|
|
scancode = GetVirtualScanCodeFromVirtualKeyCode(vkcode, 4);
|
|
extended = (scancode & KBDEXT) ? TRUE : FALSE;
|
|
|
|
rdp_instance->input->KeyboardEvent(rdp_instance->input, extended | KBD_FLAGS_RELEASE, scancode & 0xFF);
|
|
}
|
|
|
|
/** *********************************************************************
|
|
* called when shift, control, alt and meta keys are pressed/released
|
|
***********************************************************************/
|
|
|
|
- (void) flagsChanged:(NSEvent *) event
|
|
{
|
|
NSUInteger mf = [event modifierFlags];
|
|
|
|
// caps lock
|
|
if (mf == 0x10100) {
|
|
printf("TODO: caps lock is on\n");
|
|
kdcapslock = 1;
|
|
}
|
|
if (kdcapslock && (mf == 0x100)) {
|
|
kdcapslock = 0;
|
|
printf("TODO: caps lock is off\n");
|
|
}
|
|
// left shift
|
|
if ((kdlshift == 0) && ((mf & 2) != 0)) {
|
|
// left shift went down
|
|
rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_DOWN, 0x2a);
|
|
kdlshift = 1;
|
|
}
|
|
if ((kdlshift != 0) && ((mf & 2) == 0)) {
|
|
// left shift went up
|
|
rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_RELEASE, 0x2a);
|
|
kdlshift = 0;
|
|
}
|
|
|
|
// right shift
|
|
if ((kdrshift == 0) && ((mf & 4) != 0)) {
|
|
// right shift went down
|
|
rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_DOWN, 0x36);
|
|
kdrshift = 1;
|
|
}
|
|
if ((kdrshift != 0) && ((mf & 4) == 0)) {
|
|
// right shift went up
|
|
rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_RELEASE, 0x36);
|
|
kdrshift = 0;
|
|
}
|
|
|
|
// left ctrl
|
|
if ((kdlctrl == 0) && ((mf & 1) != 0)) {
|
|
// left ctrl went down
|
|
rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_DOWN, 0x1d);
|
|
kdlctrl = 1;
|
|
}
|
|
if ((kdlctrl != 0) && ((mf & 1) == 0)) {
|
|
// left ctrl went up
|
|
rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_RELEASE, 0x1d);
|
|
kdlctrl = 0;
|
|
}
|
|
|
|
// right ctrl
|
|
if ((kdrctrl == 0) && ((mf & 0x2000) != 0)) {
|
|
// right ctrl went down
|
|
rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_DOWN, 0x1d);
|
|
kdrctrl = 1;
|
|
}
|
|
if ((kdrctrl != 0) && ((mf & 0x2000) == 0)) {
|
|
// right ctrl went up
|
|
rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_RELEASE, 0x1d);
|
|
kdrctrl = 0;
|
|
}
|
|
|
|
// left alt
|
|
if ((kdlalt == 0) && ((mf & 0x20) != 0)) {
|
|
// left alt went down
|
|
rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_DOWN, 0x38);
|
|
kdlalt = 1;
|
|
}
|
|
if ((kdlalt != 0) && ((mf & 0x20) == 0)) {
|
|
// left alt went up
|
|
rdp_instance->input->KeyboardEvent(rdp_instance->input, KBD_FLAGS_RELEASE, 0x38);
|
|
kdlalt = 0;
|
|
}
|
|
|
|
// right alt
|
|
if ((kdralt == 0) && ((mf & 0x40) != 0)) {
|
|
// right alt went down
|
|
rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_DOWN, 0x38);
|
|
kdralt = 1;
|
|
}
|
|
if ((kdralt != 0) && ((mf & 0x40) == 0)) {
|
|
// right alt went up
|
|
rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_RELEASE, 0x38);
|
|
kdralt = 0;
|
|
}
|
|
|
|
// left meta
|
|
if ((kdlmeta == 0) && ((mf & 0x08) != 0)) {
|
|
// left meta went down
|
|
rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_DOWN, 0x5b);
|
|
kdlmeta = 1;
|
|
}
|
|
if ((kdlmeta != 0) && ((mf & 0x08) == 0)) {
|
|
// left meta went up
|
|
rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_RELEASE, 0x5b);
|
|
kdlmeta = 0;
|
|
}
|
|
|
|
// right meta
|
|
if ((kdrmeta == 0) && ((mf & 0x10) != 0)) {
|
|
// right meta went down
|
|
rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_DOWN, 0x5c);
|
|
kdrmeta = 1;
|
|
}
|
|
if ((kdrmeta != 0) && ((mf & 0x10) == 0)) {
|
|
// right meta went up
|
|
rdp_instance->input->KeyboardEvent(rdp_instance->input, 1 | KBD_FLAGS_RELEASE, 0x5c);
|
|
kdrmeta = 0;
|
|
}
|
|
}
|
|
|
|
- (void) setRdpInstance:(freerdp *) instance width:(int) w andHeight:(int) h windowID:(int) windowID
|
|
{
|
|
rdp_instance = instance;
|
|
context = instance->context;
|
|
width = w;
|
|
height = h;
|
|
savedWindowId = windowID;
|
|
|
|
NSRect tr = NSMakeRect(0, 0,
|
|
[[NSScreen mainScreen] frame].size.width,
|
|
[[NSScreen mainScreen] frame].size.height);
|
|
|
|
NSTrackingArea * trackingArea = [[NSTrackingArea alloc] initWithRect:tr options:NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingCursorUpdate | NSTrackingEnabledDuringMouseDrag | NSTrackingActiveAlways owner:self userInfo:nil];
|
|
|
|
[self addTrackingArea:trackingArea];
|
|
|
|
g_mrdpRailView = self;
|
|
|
|
[self becomeFirstResponder];
|
|
[self setAcceptsTouchEvents:YES];
|
|
|
|
// we want to be notified when window resizes....
|
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidResize:) name:NSWindowDidResizeNotification object:nil];
|
|
|
|
// ...moves
|
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidMove:) name:NSWindowDidMoveNotification object:nil];
|
|
|
|
// ...and becomes the key window
|
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidBecomeKey:) name:NSWindowDidBecomeKeyNotification object:nil];
|
|
}
|
|
|
|
- (void) setupBmiRep:(int) frameWidth :(int) frameHeight
|
|
{
|
|
struct rgba_data
|
|
{
|
|
char red;
|
|
char green;
|
|
char blue;
|
|
char alpha;
|
|
};
|
|
|
|
if (pixelData)
|
|
free(pixelData);
|
|
|
|
pixelData = (char *) malloc(frameWidth * frameHeight * sizeof(struct rgba_data));
|
|
bmiRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:(unsigned char **) &pixelData
|
|
pixelsWide:frameWidth
|
|
pixelsHigh:frameHeight
|
|
bitsPerSample:8
|
|
samplesPerPixel:sizeof(struct rgba_data)
|
|
hasAlpha:YES
|
|
isPlanar:NO
|
|
colorSpaceName:NSDeviceRGBColorSpace
|
|
bitmapFormat:0
|
|
bytesPerRow:frameWidth * sizeof(struct rgba_data)
|
|
bitsPerPixel:0];
|
|
}
|
|
- (void) beginGestureWithEvent:(NSEvent *)event
|
|
{
|
|
gestureEventInProgress = YES;
|
|
}
|
|
|
|
- (void) endGestureWithEvent:(NSEvent *)event
|
|
{
|
|
gestureEventInProgress = NO;
|
|
}
|
|
|
|
/**
|
|
* called when a bordered window changes size
|
|
*/
|
|
|
|
- (void) windowDidResize:(NSNotification *) notification
|
|
{
|
|
// if we are not the source of this notification, just return
|
|
if ([notification object] != [self mrdpRailWindow])
|
|
return;
|
|
|
|
// let RDP server know that window has moved
|
|
RAIL_WINDOW_MOVE_ORDER windowMove;
|
|
NSRect r = [[self window] frame];
|
|
|
|
int diffInHeight = [[self window] frame].size.height - [self frame].size.height;
|
|
r.size.height -= diffInHeight;
|
|
|
|
apple_to_windowMove(&r, &windowMove);
|
|
windowMove.windowId = self->savedWindowId;
|
|
mac_send_rail_client_event(self->context->channels, RailChannel_ClientWindowMove, &windowMove);
|
|
}
|
|
|
|
/**
|
|
* called when user moves a bordered window
|
|
*/
|
|
|
|
- (void) windowDidMove:(NSNotification *) notification
|
|
{
|
|
// if we are not the source of this notification, just return
|
|
if ([notification object] != [self mrdpRailWindow])
|
|
return;
|
|
|
|
// let RDP server know that window has moved
|
|
RAIL_WINDOW_MOVE_ORDER windowMove;
|
|
NSRect r = [[self window] frame];
|
|
|
|
int diffInHeight = [[self window] frame].size.height - [self frame].size.height;
|
|
r.size.height -= diffInHeight;
|
|
|
|
apple_to_windowMove(&r, &windowMove);
|
|
windowMove.windowId = self->savedWindowId;
|
|
mac_send_rail_client_event(self->context->channels, RailChannel_ClientWindowMove, &windowMove);
|
|
}
|
|
|
|
/**
|
|
* called when a NSWindow becomes the key window
|
|
*/
|
|
|
|
- (void) windowDidBecomeKey:(NSNotification *) notification
|
|
{
|
|
// if we are not the source of this notification, just return
|
|
if ([notification object] != [self mrdpRailWindow])
|
|
return;
|
|
|
|
if (![self activateWindow])
|
|
return;
|
|
|
|
[[self window] setAcceptsMouseMovedEvents: YES];
|
|
|
|
//if ([self activateWindow])
|
|
mac_rail_send_activate(savedWindowId);
|
|
|
|
// set_current_window(windowIndex); // ? code mis-merge?
|
|
}
|
|
|
|
- (void) releaseResources
|
|
{
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
}
|
|
|
|
void rail_cvt_from_rect(char* dest, char* src, NSRect destRect, int destWidth, int destHeight, NSRect srcRect)
|
|
{
|
|
}
|
|
|
|
/** *********************************************************************
|
|
* color space conversion used specifically in RAIL
|
|
***********************************************************************/
|
|
void rail_convert_color_space(char* destBuf, char* srcBuf, NSRect* destRect, int width, int height)
|
|
{
|
|
int i;
|
|
int j;
|
|
int numRows;
|
|
int srcX;
|
|
int srcY;
|
|
int destX;
|
|
int destY;
|
|
int pixelsPerRow;
|
|
int pixel;
|
|
int pixel1;
|
|
int pixel2;
|
|
int * src32;
|
|
int * dest32;
|
|
|
|
int destWidth = destRect->size.width;
|
|
int destHeight = destRect->size.height;
|
|
|
|
if ((!destBuf) || (!srcBuf))
|
|
return;
|
|
|
|
numRows = (destRect->origin.y + destHeight > height) ? height - destRect->origin.y : destHeight;
|
|
pixelsPerRow = destWidth;
|
|
|
|
srcX = destRect->origin.x;
|
|
srcY = destRect->origin.y;
|
|
destX = 0;
|
|
destY = 0;
|
|
|
|
for (i = 0; i < numRows; i++)
|
|
{
|
|
src32 = (int *) (srcBuf + ((srcY + i) * width + srcX) * 4);
|
|
dest32 = (int *) (destBuf + ((destY + i) * destWidth + destX) * 4);
|
|
|
|
for (j = 0; j < pixelsPerRow; j++)
|
|
{
|
|
pixel = *src32;
|
|
pixel1 = (pixel & 0x00ff0000) >> 16;
|
|
pixel2 = (pixel & 0x000000ff) << 16;
|
|
pixel = (pixel & 0xff00ff00) | pixel1 | pixel2;
|
|
|
|
*dest32 = pixel;
|
|
|
|
src32++;
|
|
dest32++;
|
|
}
|
|
}
|
|
|
|
destRect->origin.y = destHeight - destRect->origin.y - destRect->size.height;
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* let RDP server know that window has moved
|
|
*/
|
|
|
|
void rail_MoveWindow(rdpRail * rail, rdpWindow * window)
|
|
{
|
|
if (g_mrdpRailView->isMoveSizeInProgress)
|
|
return;
|
|
|
|
if (g_mrdpRailView->skipMoveWindowOnce)
|
|
{
|
|
g_mrdpRailView->skipMoveWindowOnce = NO;
|
|
return;
|
|
}
|
|
|
|
// this rect is based on Windows co-ordinates...
|
|
NSRect r;
|
|
r.origin.x = window->windowOffsetX;
|
|
r.origin.y = window->windowOffsetY;
|
|
r.size.width = window->windowWidth;
|
|
r.size.height = window->windowHeight;
|
|
|
|
windows_to_apple_cords(&r);
|
|
[[g_mrdpRailView window] setFrame:r display:YES];
|
|
}
|
|
|
|
|
|
void mac_rail_send_activate(int window_id)
|
|
{
|
|
RAIL_ACTIVATE_ORDER activate;
|
|
|
|
activate.windowId = window_id;
|
|
activate.enabled = 1;
|
|
|
|
mac_send_rail_client_event(g_mrdpRailView->context->channels, RailChannel_ClientActivate, &activate);
|
|
}
|
|
|
|
@end
|
|
|