views:

346

answers:

3

On request I have implemented support for moving an OS X window by dragging it using an area within the content part of the window, i.e replicating the drag and move functionality of the title bar but in another area.

The problem I have yet to resolve is the fact that if the user drags the mouse quickly it can leave the window area and then no more mouse move events are received.

On windows this type of problem can simply be fixed by calling the win32 method SetCapture(), what's the corresponding OSX method?

This application is a cross platform C++ application using Carbon for the OS X specific parts. (And yes, I know all about the Cocoa benefits but this is an older code base and there no time nor money for a Cocoa port at this point in time.)

I have found Carbon API methods like for example TrackMouseLocation() but can't really see how I could use them for this application. In listing 2-7 here http://developer.apple.com/legacy/mac/library/documentation/Carbon/Conceptual/Carbon%5FEvent%5FManager/Tasks/CarbonEventsTasks.html the mouse is captured but the problem is that TrackMouseLocation() blocks waiting for input. Blocking is something this application can not do since it also host a flash player that must be called many times per second.

The protototype I have assembled when trying to figure this out basically looks like this:

switch(GetEventKind(inEvent))
{
  case kEventMouseDown:
    // A silly test to make parts of the window border "draggable"
    dragging = local_loc.v < 25 || local_loc.h < 25; 
    last_screen_loc = screen_loc;
    break;
  case kEventMouseUp:
    dragging = false;
    break;
  case kEventMouseMoved:
    break;
  case kEventMouseDragged:
    if (dragging) {
      Rect rect;
      GetWindowBounds (windowRef, kWindowContentRgn, &rect);
      int dx = screen_loc.h - last_screen_loc.h;
      int dy = screen_loc.v - last_screen_loc.v;
      rect.left += dx;
      rect.right += dx;
      rect.top += dy;
      rect.bottom += dy;
      SetWindowBounds (windowRef, kWindowContentRgn, &rect);
    }
    last_screen_loc = screen_loc;
    break;

Any ideas appreciated?

A: 

Hello,

I feel you should track mouse in Window as well as out of window. Following code should solve your problem,

EventHandlerRef  m_ApplicationMouseDragEventHandlerRef;   
EventHandlerRef  m_MonitorMouseDragEventHandlerRef;

{
 OSStatus ErrStatus;

 static const EventTypeSpec kMouseDragEvents[] =
   {
  { kEventClassMouse, kEventMouseDragged }
   };

 ErrStatus = InstallEventHandler(GetEventMonitorTarget(), NewEventHandlerUPP(MouseHasDragged), GetEventTypeCount(kMouseDragEvents), kMouseDragEvents, this, &m_MonitorMouseDragEventHandlerRef);

 ErrStatus = InstallApplicationEventHandler(NewEventHandlerUPP(MouseHasDragged), GetEventTypeCount(kMouseDragEvents), kMouseDragEvents, this, &m_ApplicationMouseDragEventHandlerRef);

 return true;
}

//implement these functions
OSStatus MouseHasDragged(EventHandlerCallRef inCaller, EventRef inEvent, void *pUserData){}

Hope it helps!!

Cheers, Rahul

Rahul
A: 

I Hope It Help´s you too:

   // Get Mouse Position --> WAY 1      
printf("Get Mouse Position Way 1\n");   

HICoordinateSpace space = 2;    

HIGetMousePosition(space, NULL, &point);    
printf("Mouse Position: %.2f %.2f \n", point.x, point.y);


// Get Mouse Position --> WAY 2 
printf("Get Mouse Position Way 2\n");

CGEventRef ourEvent = CGEventCreate(NULL);
point = CGEventGetLocation(ourEvent);
printf("Mouse Position: %.2f, y = %.2f \n", (float)point.x, (float)point.y);

I´m looking for the way to get a WindowPart Reference at a certain location (over all windows of all aplications)

Certain methods in Carbon doesn´t work, always return 0 as a windowRef... Any ideas?

JxXx
A: 

You could also try just calling DragWindow in response to a click in your window's content area. I don't think you need to implement the dragging yourself.

Uncommon