📄 remote.cpp
字号:
/* ***** BEGIN LICENSE BLOCK ***** * Source last modified: $Id: remote.cpp,v 1.2.2.3 2004/10/18 18:53:31 rggammon Exp $ * * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved. * * The contents of this file, and the files included with this file, * are subject to the current version of the RealNetworks Public * Source License (the "RPSL") available at * http://www.helixcommunity.org/content/rpsl unless you have licensed * the file under the current version of the RealNetworks Community * Source License (the "RCSL") available at * http://www.helixcommunity.org/content/rcsl, in which case the RCSL * will apply. You may also obtain the license terms directly from * RealNetworks. You may not use this file except in compliance with * the RPSL or, if you have a valid RCSL with RealNetworks applicable * to this file, the RCSL. Please see the applicable RPSL or RCSL for * the rights, obligations and limitations governing use of the * contents of the file. * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL") in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your version of * this file only under the terms of the GPL, and not to allow others * to use your version of this file under the terms of either the RPSL * or RCSL, indicate your decision by deleting the provisions above * and replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient may * use your version of this file under the terms of any one of the * RPSL, the RCSL or the GPL. * * This file is part of the Helix DNA Technology. RealNetworks is the * developer of the Original Code and owns the copyrights in the * portions it created. * * This file, and the files included with this file, is distributed * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET * ENJOYMENT OR NON-INFRINGEMENT. * * Technology Compatibility Kit Test Suite(s) Location: * http://www.helixcommunity.org/content/tck * * Contributor(s): * * ***** END LICENSE BLOCK ***** */#include "remote.h"#include <X11/X.h>#include <X11/Xlib.h>#include <X11/Xatom.h>#include <gtk/gtk.h>#include <gdk/gdkx.h>#include <stdio.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#define REMOTE_COMMAND_TIMEOUT 2 /* seconds */#define MAX_WINDOW_RECURSION_DEPTH 2 /* Dig down through 2 levels of windows from the root */static gbooleancheck_children (Display* dpy, Window win, Atom atom, XID* xid, gint recursion_depth){ unsigned long num_items, after; gchar *data; gboolean found = FALSE; Window root, parent; Window *children = NULL; unsigned int num_children, i; Atom type = None; int format; if(recursion_depth >= MAX_WINDOW_RECURSION_DEPTH) { return FALSE; } XQueryTree (dpy, win, &root, &parent, &children, &num_children); for(i = 0; i < num_children; i++) { XGetWindowProperty(dpy, children[i], atom, 0, (65536 / 32), False, XA_STRING, &type, &format, &num_items, &after, (unsigned char**)&data); if (type != None && format == 8 && data) { if(strncmp(HXPLAY_REMOTE_VERSION, data, num_items) == 0) { *xid = children[i]; XFree(data); found = TRUE; break; } else { if (data) { XFree(data); } } } } if(!found) { for (i = 0; i < num_children; i++) { found = check_children (dpy, children[i], atom, xid, recursion_depth + 1); if (found) { break; } } } if(children) { XFree(children); } return found;}static GdkWindow*get_player_window(void){ Atom hxplay_remote_version; Display* dpy; Window win; XID xid = 0; gboolean result; GdkWindow* hxplay_win = NULL; hxplay_remote_version = gdk_x11_get_xatom_by_name (HXPLAY_REMOTE_VERSION_PROP); GdkWindow* gdk_root = gdk_get_default_root_window(); g_return_val_if_fail(gdk_root != NULL, NULL); dpy = GDK_WINDOW_XDISPLAY(gdk_root); win = GDK_WINDOW_XID(gdk_root); result = check_children (dpy, win, hxplay_remote_version, &xid, 0); if(result) { hxplay_win = gdk_window_foreign_new(xid); } return hxplay_win;}typedef struct{ GdkWindow* window; GdkAtom property_atom; GdkAtom xa_string_atom; gint value; gboolean is_set; } HXRemoteResponse;static GdkFilterReturnremote_property_event_filter (GdkXEvent* xevent, GdkEvent* /* event */, gpointer data){ /* This filter is called before the GdkEvent is set. */ XEvent* event = (XEvent*) xevent; if (event->type == PropertyNotify) { HXRemoteResponse* response = (HXRemoteResponse*) data; GdkAtom atom = gdk_x11_xatom_to_atom(event->xproperty.atom); if (atom == response->property_atom && event->xproperty.state == PropertyNewValue) { GdkAtom type = 0; gint format = 0; gint length = 0; gchar* ret_str = NULL; /* Retrieve the result */ gdk_property_get(response->window, response->property_atom, response->xa_string_atom, 0, G_MAXLONG - 3, TRUE, &type, &format, &length, (guchar**) &ret_str); if(length > 0 && format == 8 && ret_str) { response->value = atoi(ret_str); } else { response->value = -1; } g_free(ret_str); response->is_set = TRUE; gtk_main_quit(); } } return GDK_FILTER_CONTINUE;}static gbooleanremote_timeout (gpointer){ gtk_main_quit(); return TRUE; // Will be removed via gtk_timeout_remove}gbooleanhxremote_launch_player (const gchar* url){ gboolean got_lock; GdkWindow* hxplay_win; GdkAtom hxplay_remote_version_atom; GdkAtom hxplay_remote_lock_atom; GdkAtom hxplay_remote_command_atom; GdkAtom hxplay_remote_response_atom; GdkAtom xa_string_atom; GdkAtom type; gint format; gint length; gchar* lock_str; gchar* command_str; gchar* data; HXRemoteResponse response; memset(&response, 0, sizeof(response)); hxplay_win = get_player_window(); if(!hxplay_win) { return FALSE; } gdk_window_set_events(hxplay_win, GDK_PROPERTY_CHANGE_MASK); gdk_window_add_filter(hxplay_win, remote_property_event_filter, &response); hxplay_remote_version_atom = gdk_atom_intern(HXPLAY_REMOTE_VERSION_PROP, FALSE); hxplay_remote_lock_atom = gdk_atom_intern(HXPLAY_REMOTE_LOCK_PROP, FALSE); hxplay_remote_command_atom = gdk_atom_intern(HXPLAY_REMOTE_COMMAND_PROP, FALSE); hxplay_remote_response_atom = gdk_atom_intern(HXPLAY_REMOTE_RESPONSE_PROP, FALSE); xa_string_atom = gdk_x11_xatom_to_atom(XA_STRING); lock_str = g_strdup_printf("pid%d", getpid()); command_str = g_strdup_printf("OpenURL \"%s\"", url); /* Get a lock */ do { type = 0; format = 0; length = 0; data = NULL; gdk_x11_grab_server (); gdk_property_get(hxplay_win, hxplay_remote_lock_atom, xa_string_atom, 0, G_MAXLONG - 3, FALSE, &type, &format, &length, (guchar**)&data); if(data) { g_free(data); } if(type == xa_string_atom) { gdk_property_change (hxplay_win, hxplay_remote_lock_atom, xa_string_atom, 8, GDK_PROP_MODE_REPLACE, (const guchar*) lock_str, strlen(lock_str) + 1); got_lock = TRUE; } gdk_x11_ungrab_server (); gdk_flush(); if(!got_lock) { /* Sleep for 0.5 seconds */ usleep(500000); } } while(!got_lock); /* Set our request */ gdk_property_change (hxplay_win, hxplay_remote_command_atom, xa_string_atom, 8, GDK_PROP_MODE_REPLACE, (const guchar*) command_str, strlen(command_str) + 1); /* Wait for a response */ response.window = hxplay_win; response.property_atom = hxplay_remote_response_atom; response.xa_string_atom = xa_string_atom; gint timeout_id; timeout_id = gtk_timeout_add(1000 * REMOTE_COMMAND_TIMEOUT, remote_timeout, NULL); gtk_main(); gtk_timeout_remove(timeout_id); /* Remove our lock */ gdk_property_get(hxplay_win, hxplay_remote_lock_atom, xa_string_atom, 0, 0, TRUE, &type, &format, &length, (guchar**)&data); if(data) { g_free(data); } g_free(lock_str); g_free(command_str); return (response.value == 0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -