/** * Returns the position within the parent window. */ gcc_pure const RECT get_position() const { RECT rc; #ifdef ENABLE_SDL rc.left = get_left(); rc.top = get_top(); rc.right = get_width(); rc.bottom = get_height(); #else rc = get_screen_position(); HWND parent = ::GetParent(hWnd); if (parent != NULL) { POINT pt; pt.x = rc.left; pt.y = rc.top; ::ScreenToClient(parent, &pt); rc.left = pt.x; rc.top = pt.y; pt.x = rc.right; pt.y = rc.bottom; ::ScreenToClient(parent, &pt); rc.right = pt.x; rc.bottom = pt.y; } #endif return rc; }
void OS_X11::set_current_screen(int p_screen) { int count = get_screen_count(); if(p_screen >= count) return; if( current_videomode.fullscreen ) { Point2i position = get_screen_position(p_screen); Size2i size = get_screen_size(p_screen); XMoveResizeWindow(x11_display, x11_window, position.x, position.y, size.x, size.y); } else { if( p_screen != get_current_screen() ) { Point2i position = get_screen_position(p_screen); XMoveWindow(x11_display, x11_window, position.x, position.y); } } }
Point2 OS_X11::get_window_position() const { int x,y; Window child; XTranslateCoordinates( x11_display, x11_window, DefaultRootWindow(x11_display), 0, 0, &x, &y, &child); int screen = get_current_screen(); Point2i screen_position = get_screen_position(screen); return Point2i(x-screen_position.x, y-screen_position.y); }
void OS_X11::set_window_position(const Point2& p_position) { // Using EWMH -- Extended Window Manager Hints // to get the size of the decoration #if 0 Atom property = XInternAtom(x11_display,"_NET_FRAME_EXTENTS", True); Atom type; int format; unsigned long len; unsigned long remaining; unsigned char *data = NULL; int result; result = XGetWindowProperty( x11_display, x11_window, property, 0, 32, False, AnyPropertyType, &type, &format, &len, &remaining, &data ); long left = 0L; long top = 0L; if( result == Success ) { long *extends = (long *) data; left = extends[0]; top = extends[2]; XFree(data); } int screen = get_current_screen(); Point2i screen_position = get_screen_position(screen); left -= screen_position.x; top -= screen_position.y; XMoveWindow(x11_display,x11_window,p_position.x - left,p_position.y - top); #else XMoveWindow(x11_display,x11_window,p_position.x,p_position.y); #endif }
int OS_X11::get_current_screen() const { int x,y; Window child; XTranslateCoordinates( x11_display, x11_window, DefaultRootWindow(x11_display), 0, 0, &x, &y, &child); int count = get_screen_count(); for(int i=0; i<count; i++) { Point2i pos = get_screen_position(i); Size2i size = get_screen_size(i); if( (x >= pos.x && x <pos.x + size.width) && (y >= pos.y && y < pos.y + size.height) ) return i; } return 0; }
// Danger: This function could delete "this" void X11Window::process_message(XEvent &event, X11Window *mouse_capture_window) { switch(event.type) { case ConfigureNotify: { // Resize or Move Rect new_client_area = (event.xany.send_event == 0) ? get_screen_position() : Rect::xywh( event.xconfigure.x + event.xconfigure.border_width, event.xconfigure.y + event.xconfigure.border_width, event.xconfigure.width, event.xconfigure.height ); process_window_resize(new_client_area); break; } case ClientMessage: { // handle window manager messages Atom WM_PROTOCOLS = atoms["WM_PROTOCOLS"]; if (WM_PROTOCOLS == None) { log_event("debug", "clan::X11Window::process_message: WM_PROTOCOLS not supported by WM."); break; } else if (event.xclient.message_type == WM_PROTOCOLS) { unsigned long protocol = event.xclient.data.l[0]; if (protocol == None) { log_event("debug", "clan::X11Window::process_message: WM_PROTOCOLS event protocol supplied is None."); break; } Atom WM_DELETE_WINDOW = atoms["WM_DELETE_WINDOW"]; Atom _NET_WM_PING = atoms["_NET_WM_PING"]; if (protocol == WM_DELETE_WINDOW && site) { (site->sig_window_close)(); } else if (protocol == _NET_WM_PING) { XSendEvent(handle.display, RootWindow(handle.display, handle.screen), False, SubstructureNotifyMask | SubstructureRedirectMask, &event); } } break; } case Expose: { // Window exposure repaint_request = true; break; } case FocusIn: if (site) (site->sig_got_focus)(); break; case FocusOut: if (site) { if (!has_focus()) // For an unknown reason, FocusOut is called when clicking on title bar of window { (site->sig_lost_focus)(); } } break; case PropertyNotify: { // Iconify, Maximized, ... if (!site) break; Atom _NET_WM_STATE = atoms["_NET_WM_STATE"]; Atom WM_STATE = atoms["WM_STATE"]; // legacy. if (_NET_WM_STATE != None && event.xproperty.atom == _NET_WM_STATE && event.xproperty.state == PropertyNewValue) { if (is_minimized()) { if (!minimized && site != nullptr) (site->sig_window_minimized)(); minimized = true; maximized = false; } else if (is_maximized()) { if (!maximized && site != nullptr) (site->sig_window_maximized)(); if (minimized && site != nullptr) { // generate resize events for minimized -> maximized transition Rectf rectf = get_geometry(); rectf.left /= pixel_ratio; rectf.top /= pixel_ratio; rectf.right /= pixel_ratio; rectf.bottom /= pixel_ratio; (site->sig_window_moved)(); if (site->func_window_resize) (site->func_window_resize)(rectf); if (callback_on_resized) callback_on_resized(); (site->sig_resize)(rectf.get_width(), rectf.get_height()); } minimized = false; maximized = true; } else { if ((minimized || maximized) && site != nullptr) (site->sig_window_restored)(); minimized = false; maximized = false; } } else if (WM_STATE != None && event.xproperty.atom == WM_STATE && event.xproperty.state == PropertyNewValue) { if (is_minimized()) { if (!minimized && site != nullptr) (site->sig_window_minimized)(); minimized = true; } else { if (minimized && site != nullptr) (site->sig_window_restored)(); minimized = false; } } break; } case KeyRelease: case KeyPress: if (get_keyboard_provider()) { get_keyboard_provider()->received_keyboard_input(keyboard, event.xkey); } break; case ButtonPress: case ButtonRelease: if (mouse_capture_window->get_mouse_provider() && event.xany.send_event==0) { if (callback_on_clicked) { // This callback is required for GL layered windows if (!callback_on_clicked(event.xbutton)) break; } if (this != mouse_capture_window) // This is so you can capture mouse events in another window, as if it was this window (Set by capture_mouse()) { Rect this_scr = client_area; Rect capture_scr = mouse_capture_window->client_area; event.xbutton.x += this_scr.left - capture_scr.left; event.xbutton.y += this_scr.top - capture_scr.top; } mouse_capture_window->get_mouse_provider()->received_mouse_input(mouse_capture_window->mouse, event.xbutton); } break; case MotionNotify: if (mouse_capture_window->get_mouse_provider() && event.xany.send_event == 0) { if (this != mouse_capture_window) // This is so you can capture mouse events in another window, as if it was this window (Set by capture_mouse()) { Rect this_scr = client_area; Rect capture_scr = mouse_capture_window->client_area; event.xmotion.x += this_scr.left - capture_scr.left; event.xmotion.y += this_scr.top - capture_scr.top; } mouse_capture_window->get_mouse_provider()->received_mouse_move(mouse_capture_window->mouse, event.xmotion); } break; case SelectionClear: // New clipboard selection owner clipboard.event_selection_clear(event.xselectionclear); break; case SelectionNotify: clipboard.event_selection_notify(); break; case SelectionRequest: // Clipboard requests clipboard.event_selection_request(event.xselectionrequest); break; default: break; } }