/* Window server implementation Copyright (C) 2001 Johan Rydberg. All Rights Reserved. This file is part of Crust. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include "SXWindowServer.h" #include "SXWindowTheme.h" #include "SXWindow.h" #include "SFEvent.h" #include "priv.h" #define kButtonStateUp 0 #define kButtonStateDown 1 /* Signal handler for "event_mouse_down" for a button. What we should do is to redraw the button in "down" state and record the state change. SIGNAL_ARG is the button that we're controling. User data for tracking area is a pointer to the window. */ void WSSignalButtonDown (CFTypeRef tracking_area, void *signal_arg, void *signal_data) { SXWindowThemeElementRef button = (SXWindowThemeElementRef) signal_arg; if (button->state == kButtonStateDown) { CFLog ("*** WSSignalButtonDown: Button was already down. Strange.\n"); return; } button->state = kButtonStateDown; CFLog ("*** WSSignalButtonDown: Should redraw button\n"); } void WSSignalButtonUp (CFTypeRef tracking_area, void *signal_arg, void *signal_data) { SFTrackingAreaRef area = (SFTrackingAreaRef) tracking_area; SFWindowRef window = SFTrackingAreaUserData (area); SFEvent event; /* We could not emit a signal - send event to application instead. */ event.event_code = 666; event.event_object = window; _SFEventPost (&event); } /* Titlebar signal handler for "event_mouse_down" event. */ void WSSignalTitlebarDown (CFTypeRef tracking_area, void *signal_arg, void *signal_data) { struct EventDataMouseDown *data = (struct EventDataMouseDown *) signal_data; SFWindowRef window = (SFWindowRef) signal_arg; if (data->button == 0) /* ??? NOT VERY PRETTY. */ { window->mouse_pos_x = data->root_x; window->mouse_pos_y = data->root_y; window->flag_drag = true; SFTrackingAreaGrabCursor (tracking_area); } } /* Titlebar signal handler for "event_mouse_up" event. */ void WSSignalTitlebarUp (CFTypeRef tracking_area, void *signal_arg, void *signal_data) { struct EventDataMouseDown *data = (struct EventDataMouseDown *) signal_data; SFWindowRef window = (SFWindowRef) signal_arg; if (data->button == 0) /* ??? NOT VERY PRETTY. */ { window->flag_drag = false; SFTrackingAreaUngrabCursor (tracking_area); } } /* Titlebar signal handler for "event_mouse_move" event. We move the window. */ void WSSignalTitlebarMove (CFTypeRef tracking_area, void *signal_arg, void *signal_data) { struct EventDataMouseMove *data = (struct EventDataMouseMove *) signal_data; SFWindowRef window = (SFWindowRef) signal_arg; if (window->flag_drag) { int dx, dy; dx = data->root_x - window->mouse_pos_x; dy = data->root_y - window->mouse_pos_y; window->mouse_pos_x = data->root_x; window->mouse_pos_y = data->root_y; #if 1 SFLayerMoveRelative (window->window_layer, dx, dy); #endif } } /* Called when the mouse cursor enters a surface. EVENT_PORT is (hopefully) connected to one of our surfaces. When this is called we should have no focused tracking areas. */ void S_window_server_event_focus_enter (mach_port_t event_port, int x, int y) { SFTrackingAreaRef tracking_area; SFSurfaceRef surface; SFEvent event; int count, i; surface = _SFEventLookupObject (event_port); if (surface) { GFPoint point = GFPointMake (x, y), delta; count = CFArrayCount (surface->track_array); /* Loop through all tracking areas. */ for (i = 0; i < count; i++) { tracking_area = CFArrayAt (surface->track_array, i); if (! tracking_area) continue; if (GFRectContains (tracking_area->area, point)) { delta = GFPointSubtract (point, tracking_area->area.origin); /* Okey - we record that this tracking area have focus. */ tracking_area->flag_focus = 1; if (! (tracking_area->event_mask & kSFEventMouseEnteredMask)) continue; if (CFRuntimeSignalEmit (tracking_area, "event_focus_enter", 0)) continue; /* We could not emit a signal - send event to application instead. */ event.event_code = kSFEventMouseEnteredCode; event.event_object = tracking_area; event.mouse_move_event.x = (int) delta.x; event.mouse_move_event.y = (int) delta.y; _SFEventPost (&event); } } } else CFLog ("[*** window server: stray event: focus enter ***]\n"); } /* Called when the mouse cursor leaves a surface. EVENT_PORT is (hopefully) connected to one of our surfaces. */ void S_window_server_event_focus_leave (mach_port_t event_port) { SFTrackingAreaRef tracking_area; SFSurfaceRef surface; SFEvent event; int count, i; surface = _SFEventLookupObject (event_port); if (surface) { count = CFArrayCount (surface->track_array); /* Loop through all tracking areas. */ for (i = 0; i < count; i++) { tracking_area = CFArrayAt (surface->track_array, i); if (! tracking_area) continue; if (tracking_area->flag_focus) { /* Okey - we record that this tracking area have focus. */ tracking_area->flag_focus = 0; if (! (tracking_area->event_mask & kSFEventMouseExitedMask)) continue; if (CFRuntimeSignalEmit (tracking_area, "event_focus_leave", 0)) continue; /* We could not emit a signal - send event to application instead. */ event.event_code = kSFEventMouseExitedCode; event.event_object = tracking_area; _SFEventPost (&event); } } } else CFLog ("[*** window server: stray event: focus leave ***]\n"); } /* Called when the mouse cursor moves within a surface. EVENT_PORT is (hopefully) connected to one of our surfaces. X and Y is the location of the cursor, reltave to the surface. */ void S_window_server_event_mouse_move (mach_port_t event_port, int x, int y, int root_x, int root_y) { struct EventDataMouseMove signal_data; SFTrackingAreaRef tracking_area; SFSurfaceRef surface; SFEvent event; int count, i; #if 0 CFLog ("[*** window server: Got mouse move (%d, %d) ***]\n", x, y); #endif surface = _SFEventLookupObject (event_port); if (surface) { GFPoint point = GFPointMake (x, y), delta; /* If someone have grabbed the cursor we send motion events directly to it. */ if (surface->track_cursor) { delta = GFPointSubtract (point, surface->track_cursor->area.origin); signal_data.x = (int) delta.x; signal_data.y = (int) delta.y; signal_data.root_x = root_x; signal_data.root_y = root_y; if (! CFRuntimeSignalEmit (surface->track_cursor, "event_mouse_move", &signal_data)) { event.event_code = kSFEventMouseMovedCode; event.event_object = surface->track_cursor; event.mouse_move_event.x = (int) delta.x; event.mouse_move_event.y = (int) delta.y; _SFEventPost (&event); } return; } count = CFArrayCount (surface->track_array); /* Loop through all tracking areas. */ for (i = 0; i < count; i++) { tracking_area = CFArrayAt (surface->track_array, i); if (! tracking_area) continue; /* First we check if the POINT is contained within TRACKING_AREA's area. If it is, and we it didn't have focus before we send a "focus enter" event to it. If it had focus, we just send a "mouse moved" event. */ if (GFRectContains (tracking_area->area, point)) { delta = GFPointSubtract (point, tracking_area->area.origin); /* Tracking area did not have focus - send enter event. */ if (tracking_area->flag_focus == 0) { /* Okey - we record that this tracking area have focus. */ tracking_area->flag_focus = 1; if (! (tracking_area->event_mask & kSFEventMouseEnteredMask)) continue; if (CFRuntimeSignalEmit (tracking_area, "event_focus_enter", 0)) continue; event.event_code = kSFEventMouseEnteredCode; event.event_object = tracking_area; event.mouse_move_event.x = (int) delta.x; event.mouse_move_event.y = (int) delta.y; _SFEventPost (&event); } /* Tracking area already had focus, send "mouse moved" event. */ else { if (! (tracking_area->event_mask & kSFEventMouseMovedMask)) continue; signal_data.x = (int) delta.x; signal_data.y = (int) delta.y; signal_data.root_x = root_x; signal_data.root_y = root_y; /* ??? emit coordinates here? */ if (CFRuntimeSignalEmit (tracking_area, "event_mouse_move", &signal_data)) return; event.event_code = kSFEventMouseMovedCode; event.event_object = tracking_area; event.mouse_move_event.x = (int) delta.x; event.mouse_move_event.y = (int) delta.y; _SFEventPost (&event); } } /* If point is NOT within tracking area we check if tracking area had focus - if it did, send a focus enter event. */ else if (tracking_area->flag_focus == 1) { /* Okey - we record that this tracking area have focus. */ tracking_area->flag_focus = 0; if (! (tracking_area->event_mask & kSFEventMouseExitedMask)) continue; if (CFRuntimeSignalEmit (tracking_area, "event_focus_leave", 0)) continue; /* We could not emit a signal - send event to application instead. */ event.event_code = kSFEventMouseExitedCode; event.event_object = tracking_area; _SFEventPost (&event); } } } else CFLog ("[*** window server: stray event: move move ***]\n"); } /* Called when a mouse button is pressed within a surface. EVENT_PORT is (hopefully) connected to one of our surfaces. BUTTON is the button number that was pressed. X, Y is the current location of the cursor, relative to the surface. */ /* ??? add enter/leave detection here? */ void S_window_server_event_mouse_down (mach_port_t event_port, int button, int x, int y, int root_x, int root_y) { struct EventDataMouseDown signal_data; SFTrackingAreaRef tracking_area; SFSurfaceRef surface; SFEvent event; int count, i; #if 0 CFLog ("[*** window server: Got mouse down %d (%d, %d) ***]\n", button, x, y); #endif surface = _SFEventLookupObject (event_port); if (surface) { GFPoint point = GFPointMake (x, y), delta; count = CFArrayCount (surface->track_array); /* If someone have grabbed the cursor we send motion events directly to it. */ if (surface->track_cursor) { delta = GFPointSubtract (point, surface->track_cursor->area.origin); signal_data.button = button; signal_data.x = (int) delta.x; signal_data.y = (int) delta.y; signal_data.root_x = root_x; signal_data.root_y = root_y; if (! CFRuntimeSignalEmit (surface->track_cursor, "event_mouse_down", &signal_data)) { /* We could not emit a signal - send event to application instead. */ event.event_code = kSFEventMouseDownCode; event.event_object = surface->track_cursor; event.mouse_move_event.x = (int) delta.x; event.mouse_move_event.y = (int) delta.y; event.mouse_press_event.button = button; _SFEventPost (&event); } return; } /* Loop through all tracking areas. */ for (i = 0; i < count; i++) { tracking_area = CFArrayAt (surface->track_array, i); if (! tracking_area) continue; if (GFRectContains (tracking_area->area, point)) { if (! (tracking_area->event_mask & kSFEventMouseDownMask)) continue; delta = GFPointSubtract (point, tracking_area->area.origin); signal_data.button = button; signal_data.x = (int) delta.x; signal_data.y = (int) delta.y; signal_data.root_x = root_x; signal_data.root_y = root_y; if (CFRuntimeSignalEmit (tracking_area, "event_mouse_down", &signal_data)) continue; /* We could not emit a signal - send event to application instead. */ event.event_code = kSFEventMouseDownCode; event.event_object = tracking_area; event.mouse_move_event.x = (int) delta.x; event.mouse_move_event.y = (int) delta.y; event.mouse_press_event.button = button; _SFEventPost (&event); } } } else CFLog ("[*** window server: Got mouse down %d (%d, %d) ***]\n", button, x, y); } /* Called when a mouse button is released within a surface. EVENT_PORT is (hopefully) connected to one of our surfaces. BUTTON is the button number that was released. X, Y is the current location of the cursor, relative to the surface. If we can not post a signal on the surface we post an event to the application. */ void S_window_server_event_mouse_up (mach_port_t event_port, int button, int x, int y, int root_x, int root_y) { struct EventDataMouseDown signal_data; SFTrackingAreaRef tracking_area; SFSurfaceRef surface; SFEvent event; int count, i; #if 0 CFLog ("[*** window server: Got mouse up %d (%d, %d) ***]\n", button, x, y); #endif surface = _SFEventLookupObject (event_port); if (surface) { GFPoint point = GFPointMake (x, y), delta; count = CFArrayCount (surface->track_array); /* If someone have grabbed the cursor we send motion events directly to it. */ if (surface->track_cursor) { delta = GFPointSubtract (point, surface->track_cursor->area.origin); signal_data.button = button; signal_data.x = (int) delta.x; signal_data.y = (int) delta.y; signal_data.root_x = root_x; signal_data.root_y = root_y; if (! CFRuntimeSignalEmit (surface->track_cursor, "event_mouse_up", &signal_data)) { /* We could not emit a signal - send event to application instead. */ event.event_code = kSFEventMouseUpCode; event.event_object = surface->track_cursor; event.mouse_move_event.x = (int) delta.x; event.mouse_move_event.y = (int) delta.y; event.mouse_press_event.button = button; _SFEventPost (&event); } return; } /* Loop through all tracking areas. */ for (i = 0; i < count; i++) { tracking_area = CFArrayAt (surface->track_array, i); if (! tracking_area) continue; if (GFRectContains (tracking_area->area, point)) { if (! (tracking_area->event_mask & kSFEventMouseUpMask)) continue; signal_data.button = button; signal_data.x = (int) delta.x; signal_data.y = (int) delta.y; signal_data.root_x = root_x; signal_data.root_y = root_y; delta = GFPointSubtract (point, tracking_area->area.origin); if (CFRuntimeSignalEmit (tracking_area, "event_mouse_up", &signal_data)) continue; /* We could not emit a signal - send event to application instead. */ event.event_code = kSFEventMouseUpCode; event.event_object = tracking_area; event.mouse_move_event.x = (int) delta.x; event.mouse_move_event.y = (int) delta.y; event.mouse_press_event.button = button; _SFEventPost (&event); } } } else CFLog ("[*** window server: Got mouse up %d (%d, %d) ***]\n", button, x, y); } /* Called by the application manager when it just have activated another window. We should redraw ourself as inactive and post an event. */ void S_window_server_window_deactive (mach_port_t event_port) { }